Compare commits

...
Author SHA1 Message Date
Diego Imbert 9998ca3810 (stash) navbar 2025-09-24 17:00:54 +02:00
Diego Imbert e64b069d77 nit typo 2025-09-24 16:36:54 +02:00
Diego Imbert 13f58cb5f0 nit 2025-09-24 15:56:41 +02:00
Diego Imbert 0f30574f55 resize transition in schemaform 2025-09-24 14:39:13 +02:00
Diego Imbert ba551a641d nit 2025-09-24 11:45:40 +02:00
Diego Imbert ec5142d984 nit 2025-09-24 11:33:07 +02:00
Diego Imbert 082960ce21 Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-24 11:29:06 +02:00
Diego Imbert 4d014abfa9 (stash) fix select dropdown animation teleporting from bottom to top 2025-09-23 18:28:13 +02:00
Diego Imbert 93e59a9327 started updating PropertyEditor 2025-09-23 18:04:22 +02:00
Diego Imbert 890e6d0bec nit 2025-09-23 17:35:50 +02:00
Diego Imbert d69c2ed212 fix json toggle appearing in fileinputs 2025-09-23 17:24:09 +02:00
Diego Imbert 617948aa49 nit 2025-09-23 17:08:36 +02:00
Diego Imbert 664b2e2335 array input nits 2025-09-23 17:01:24 +02:00
Diego Imbert 8b01825dc9 prettier json toggle and array inputs 2025-09-23 16:50:23 +02:00
Diego Imbert 4f5c41064f nits 2025-09-23 16:22:03 +02:00
Diego Imbert 77d157b732 fix nested objects 2025-09-23 15:56:24 +02:00
Diego Imbert 114399c848 Merge branch 'di/fix-missing-effect-pre' into di/flow-input-redesign 2025-09-23 13:57:01 +02:00
Diego Imbert 866a7fe391 forgot $effect.pre 2025-09-23 13:56:10 +02:00
Diego Imbert 7b07295bd2 Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-23 13:49:02 +02:00
Diego Imbert c48a3da3b3 missing $derived and $state => reactivity issue when switching between DynSelect and DynMultiselect 2025-09-23 12:59:22 +02:00
Diego Imbert ac918a84b6 Prevent crash when selecting dyn-multiselect 2025-09-23 12:44:07 +02:00
Diego Imbert c4f516fa47 Fix multiselect styling 2025-09-23 12:28:18 +02:00
Diego Imbert 4e892b2ed6 rounded nit 2025-09-23 11:18:51 +02:00
Diego Imbert 8b8025e60a fix togglebutton border in darkmode 2025-09-23 11:13:17 +02:00
Diego Imbert 6d9b0e1f2c Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-23 11:13:05 +02:00
Diego Imbert 87ab80fcc4 nicer refresh button in Test This Step 2025-09-22 16:27:10 +02:00
Diego Imbert a498b09dd1 fix textarea styling 2025-09-22 16:16:23 +02:00
Diego Imbert 0941ecc077 Fix FileInput and S3 Arg Input 2025-09-22 15:42:05 +02:00
Diego Imbert cd3b1e43c3 Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-22 14:35:43 +02:00
Diego Imbert a4d25cb529 fix scrollbar 2025-09-22 13:55:17 +02:00
Diego Imbert a1fa8e0068 ResourcePicker Add and Refresh btn 2025-09-22 13:38:57 +02:00
Diego Imbert 5aa89d213c change resource edit button pos 2025-09-22 11:40:55 +02:00
Diego Imbert 1c142cc1a7 ai provider toggle button more 2025-09-22 10:57:09 +02:00
Diego Imbert 797e49fbfe Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-19 20:13:04 +02:00
Diego Imbert bb6399fff6 jsonEditor pretty 2025-09-19 18:01:43 +02:00
Diego Imbert 187b1065e1 Refresh button in flow picker quick 2025-09-19 17:43:23 +02:00
Diego Imbert b9c9914024 nit 2025-09-19 16:39:47 +02:00
Diego Imbert 31b5ace88a select dropdown slide 2025-09-19 16:36:10 +02:00
Diego Imbert 4708118f96 no-default-style 2025-09-19 16:33:32 +02:00
Diego Imbert c20d094408 smaller ${...} badge 2025-09-19 16:11:00 +02:00
Diego Imbert b6d6795418 aiproviderpicker + nits 2025-09-19 16:05:47 +02:00
Diego Imbert 5d3f3c1999 select nits 2025-09-19 14:51:06 +02:00
Diego Imbert 41604e6513 fix jittery fake monaco placeholder 2025-09-19 14:33:32 +02:00
Diego Imbert 20306f8e87 update select style 2025-09-19 14:24:19 +02:00
Diego Imbert 28feda1791 styling in js mode 2025-09-19 14:11:48 +02:00
Diego Imbert a95c566ee3 force focus border for TemplateEditor 2025-09-19 11:44:47 +02:00
Diego Imbert 22999e53fd text hint 2025-09-19 11:19:40 +02:00
Diego Imbert 7fa3eb434e prevent double onpointerdown when clicking button to close 2025-09-18 21:09:18 +02:00
Diego Imbert 631be4735a Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-18 21:07:41 +02:00
Diego Imbert 060dbc8e73 Merge remote-tracking branch 'origin/main' into di/flow-input-redesign 2025-09-18 20:10:46 +02:00
Diego Imbert ba025e08f5 Prettier TemplateEditor 2025-09-18 14:36:00 +02:00
Diego Imbert e73a72af8c ResizeTransitionWrapper 2025-09-18 11:34:04 +02:00
Diego Imbert 357b1d0f82 pretty Fill Inputs button 2025-09-18 11:13:01 +02:00
Diego Imbert 4e15bf1029 fix connecting btn changing size 2025-09-18 10:56:53 +02:00
Diego Imbert ae8788b8d1 always show static/f selector 2025-09-18 10:45:17 +02:00
Diego Imbert 059b2a5ca7 started improving input transform form 2025-09-17 18:24:50 +02:00
Diego Imbert fc818e9ed8 Monaco transparent bg 2025-09-17 16:13:02 +02:00
48 changed files with 956 additions and 601 deletions
@@ -8,6 +8,7 @@
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
import ResourcePicker from './ResourcePicker.svelte'
import ToggleButtonMore from './common/toggleButton-v2/ToggleButtonMore.svelte'
interface ProviderValue {
kind?: AIProvider
@@ -154,22 +155,34 @@
}
</script>
<div class="w-full flex flex-col gap-3">
<div class="w-full flex flex-col gap-1 bg-surface-secondary rounded-md">
<!-- Provider Selection -->
<div class="flex flex-col gap-2">
<ToggleButtonGroup selected={value?.kind} onSelected={onProviderChange} {disabled} wrap>
<ToggleButtonGroup
selected={value?.kind}
onSelected={onProviderChange}
{disabled}
wrap
tabListClass="w-full"
>
{#snippet children({ item })}
{#each providerOptions as option}
{#each providerOptions.slice(0, 3) as option}
<ToggleButton value={option.value} label={option.label} {item} />
{/each}
<ToggleButtonMore
class="ml-auto"
togglableItems={providerOptions.slice(3)}
{item}
bind:selected={() => value?.kind, (v) => v && onProviderChange(v)}
/>
{/snippet}
</ToggleButtonGroup>
</div>
<!-- Resource Selection -->
<div class="flex flex-col border border-gray-200 rounded-md p-2 gap-2">
<div class="flex flex-col rounded-md p-2 gap-2">
<div class="flex flex-col gap-1">
<p class="text-sm font-medium text-primary">resource</p>
<p class="text-sm font-normal text-tertiary">resource</p>
<ResourcePicker
bind:value={
() => resourceValueToPath(value?.resource),
@@ -183,12 +196,13 @@
disabled={disabled || !value?.kind}
placeholder="Select resource"
selectFirst={true}
selectInputClass="!bg-surface"
/>
</div>
<!-- Model Selection -->
<div class="flex flex-col gap-1">
<p class="text-sm font-medium text-primary">model</p>
<p class="text-sm font-normal text-tertiary">model</p>
<Select
{items}
bind:value={value.model}
@@ -203,6 +217,7 @@
clearable={false}
noItemsMsg={'No models available'}
bind:filterText
inputClass="min-h-10 !bg-surface disabled:!bg-surface-disabled"
/>
</div>
</div>
+5 -2
View File
@@ -12,6 +12,7 @@
valid: boolean
create: boolean
enumLabels?: Record<string, string> | undefined
selectClass?: string
}
let {
@@ -22,7 +23,8 @@
defaultValue,
valid,
create,
enumLabels = undefined
enumLabels = undefined,
selectClass = ''
}: Props = $props()
const dispatch = createEventDispatcher()
@@ -46,7 +48,7 @@
<div class="w-full flex-col">
<div class="w-full">
<Select
inputClass={valid ? '' : '!border-red-500/60'}
error={!valid}
clearable
{disabled}
autofocus={autofocus ?? undefined}
@@ -62,6 +64,7 @@
}
onFocus={() => dispatch('focus')}
onBlur={() => dispatch('blur')}
inputClass={selectClass}
/>
</div>
</div>
+240 -172
View File
@@ -46,6 +46,7 @@
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'
interface Props {
label?: string
@@ -71,6 +72,7 @@
properties?: { [name: string]: SchemaProperty }
}
| undefined
lightHeaderFont?: boolean
displayHeader?: boolean
properties?: { [name: string]: SchemaProperty } | undefined
nestedRequired?: string[] | undefined
@@ -120,6 +122,8 @@
| undefined
workspace?: string | undefined
actions?: import('svelte').Snippet
innerBottomSnippet?: import('svelte').Snippet
fieldHeaderActions?: import('svelte').Snippet
}
let {
@@ -133,7 +137,7 @@
oneOf = $bindable(undefined),
required = false,
pattern = $bindable(undefined),
valid = $bindable(undefined),
valid = $bindable(undefined), // Note : this should not exist, valid and error should be one coherent state
enum_ = $bindable(undefined),
disabled = false,
itemsType = $bindable(undefined),
@@ -176,7 +180,10 @@
appPath = undefined,
computeS3ForceViewerPolicies = undefined,
workspace = undefined,
actions
actions,
innerBottomSnippet,
fieldHeaderActions,
lightHeaderFont = false
}: Props = $props()
$effect(() => {
@@ -463,6 +470,11 @@
let { debounced, clearDebounce } = debounce(() => compareValues(value), 50)
let inputCat = $derived(computeInputCat(type, format, itemsType?.type, enum_, contentEncoding))
let displayJsonToggleHeader = $derived(
displayHeader &&
inputCat === 'list' &&
!(itemsType?.resourceType === 's3_object' || itemsType?.resourceType === 's3object')
)
$effect(() => {
oneOf && untrack(() => updateOneOfSelected(oneOf))
})
@@ -582,24 +594,43 @@
</div>
{/if}
{#if displayHeader}
<FieldHeader
prettify={prettifyHeader}
label={title && !emptyString(title) ? title : label}
{disabled}
{required}
{type}
{contentEncoding}
{format}
{simpleTooltip}
{lightHeader}
{displayType}
labelClass={css?.label?.class}
/>
{/if}
<div class="flex">
<FieldHeader
prettify={prettifyHeader}
label={title && !emptyString(title) ? title : label}
{disabled}
{required}
{type}
{contentEncoding}
{format}
{simpleTooltip}
{lightHeader}
{displayType}
labelClass={twMerge(
lightHeaderFont ? '!font-normal !text-sm text-tertiary' : '',
css?.label?.class
)}
/>
<div class="ml-auto flex gap-2">
{#if displayJsonToggleHeader}
<Toggle
on:change={(e) => {
// Once the user has changed the input type, we should not change it back automatically
if (!hasIsListJsonChanged) {
hasIsListJsonChanged = true
}
{#if description}
<div class={twMerge('text-xs italic pb-1 text-secondary', css?.description?.class)}>
<pre class="font-main whitespace-normal">{description}</pre>
evalValueToRaw()
isListJson = !isListJson
}}
checked={isListJson}
textClass="text-secondary"
size="xs"
options={{ left: 'json' }}
/>
{/if}
{@render fieldHeaderActions?.()}
</div>
</div>
{/if}
@@ -624,7 +655,22 @@
/>
{:else}
<div class="relative w-full">
<input
<TextInput
inputProps={{
autofocus,
onfocus: bubble('focus'),
onblur: bubble('blur'),
disabled,
type: 'number',
onkeydown: () => (ignoreValueUndefined = true),
placeholder: placeholder ?? defaultValue ?? '',
min: extra['min'],
max: extra['max']
}}
{error}
bind:value
/>
<!-- <input
{autofocus}
onfocus={bubble('focus')}
onblur={bubble('blur')}
@@ -640,7 +686,7 @@
bind:value
min={extra['min']}
max={extra['max']}
/>
/> -->
</div>
{/if}
{:else if inputCat == 'boolean'}
@@ -674,6 +720,7 @@
bind:editor
{appPath}
{computeS3ForceViewerPolicies}
bottom={innerBottomSnippet}
/>
{:else if inputCat == 'object' && format == 'json-schema'}
{#await import('$lib/components/EditableSchemaForm.svelte')}
@@ -717,8 +764,9 @@
<Module.default code={JSON.stringify(value, null, 2)} bind:value />
{/await}
{:else}
<div class="py-4 pr-2 pl-6 border rounded-md w-full">
<div class="px-2 pt-2 border rounded-md w-full">
<SchemaForm
lightHeaderFont
{onlyMaskPassword}
{disablePortal}
{disabled}
@@ -763,14 +811,34 @@
/>
</div>
{:else}
<div class="w-full">
<div class="w-full flex flex-col gap-y-1">
{#key redraw}
{#if Array.isArray(value)}
{#each value ?? [] as v, i}
{#if i < itemsLimit}
<div class="flex max-w-md mt-1 w-full items-center">
<div class="flex w-full items-center relative">
{#snippet deleteItemBtn()}
<button
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
aria-label="Clear"
onclick={() => {
value = value.filter((_, index) => index !== i)
redraw += 1
}}
>
<X size={14} />
</button>
{/snippet}
{#if itemsType?.type == 'number'}
<input type="number" bind:value={value[i]} id="arg-input-number-array" />
<TextInput
inputProps={{ type: 'number', id: 'arg-input-number-array' }}
class="pr-8"
bind:value={value[i]}
/>
<div class="absolute z-10 right-1.5">
{@render deleteItemBtn()}
</div>
{:else if itemsType?.type == 'string' && itemsType?.contentEncoding == 'base64'}
<input
type="file"
@@ -778,6 +846,7 @@
onchange={(x) => fileChanged(x, (val) => (value[i] = val))}
multiple={false}
/>
{@render deleteItemBtn()}
{:else if itemsType?.type == 'object' && itemsType?.resourceType === undefined && itemsType?.properties === undefined && !(format?.startsWith('resource-') && resourceTypes?.includes(format.split('-')[1]))}
{#await import('$lib/components/JsonEditor.svelte')}
<Loader2 class="animate-spin" />
@@ -787,6 +856,7 @@
bind:value={value[i]}
/>
{/await}
{@render deleteItemBtn()}
{:else if Array.isArray(itemsType?.enum)}
<ArgEnum
create={extra['disableCreate'] != true}
@@ -804,6 +874,7 @@
enum_={itemsType?.enum ?? []}
enumLabels={extra['enumLabels']}
/>
{@render deleteItemBtn()}
{:else if (itemsType?.type == 'resource' && itemsType?.resourceType && resourceTypes?.includes(itemsType.resourceType)) || (format?.startsWith('resource-') && resourceTypes?.includes(format.split('-')[1]))}
{@const resourceFormat =
itemsType?.type == 'resource' &&
@@ -816,6 +887,7 @@
format={resourceFormat}
defaultValue={undefined}
/>
{@render deleteItemBtn()}
{:else if itemsType?.type == 'resource'}
{#await import('$lib/components/JsonEditor.svelte')}
<Loader2 class="animate-spin" />
@@ -832,9 +904,11 @@
bind:value={value[i]}
/>
{/await}
{@render deleteItemBtn()}
{:else if itemsType?.type === 'object' && itemsType?.properties}
<div class="p-8 border rounded-md w-full">
<SchemaForm
lightHeaderFont
{onlyMaskPassword}
{disablePortal}
{disabled}
@@ -843,20 +917,17 @@
bind:args={value[i]}
/>
</div>
{@render deleteItemBtn()}
{:else}
<input type="text" bind:value={value[i]} id="arg-input-array" />
<TextInput
inputProps={{ type: 'text', id: 'arg-input-array' }}
class="pr-8"
bind:value={value[i]}
/>
<div class="absolute z-10 right-1.5">
{@render deleteItemBtn()}
</div>
{/if}
<button
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
aria-label="Clear"
onclick={() => {
value = value.filter((_, index) => index !== i)
redraw += 1
}}
>
<X size={14} />
</button>
</div>
{/if}
{/each}
@@ -869,7 +940,7 @@
{#if value.startsWith('$res:')}
{@render resourceInput()}
{:else}
<div class="text-red-500">
<div class="text-red-500 text-xs">
Invalid string value: "{value}", expected array. Click add item to turn it
into an array.
</div>
@@ -877,59 +948,58 @@
{/if}
{/key}
</div>
<div class="flex mt-2 gap-20 items-baseline">
<Button
variant="border"
color="light"
size="xs"
btnClasses="mt-1"
on:click={() => {
if (value == undefined || !Array.isArray(value)) {
value = []
}
if (itemsType?.type == 'number') {
value = value.concat(0)
} else if (
(itemsType?.type == 'object' &&
!(
format?.startsWith('resource-') &&
resourceTypes?.includes(format.split('-')[1])
)) ||
(itemsType?.type == 'resource' &&
!(
itemsType?.resourceType && resourceTypes?.includes(itemsType?.resourceType)
))
) {
value = value.concat({})
} else {
value = value.concat('')
}
}}
id="arg-input-add-item"
startIcon={{ icon: Plus }}
>
Add item
</Button>
</div>
<Button
variant="border"
color="light"
size="xs"
btnClasses="text-tertiary"
wrapperClasses="w-full mt-2"
on:click={() => {
if (value == undefined || !Array.isArray(value)) {
value = []
}
if (itemsType?.type == 'number') {
value = value.concat(0)
} else if (
(itemsType?.type == 'object' &&
!(
format?.startsWith('resource-') &&
resourceTypes?.includes(format.split('-')[1])
)) ||
(itemsType?.type == 'resource' &&
!(itemsType?.resourceType && resourceTypes?.includes(itemsType?.resourceType)))
) {
value = value.concat({})
} else {
value = value.concat('')
}
}}
id="arg-input-add-item"
startIcon={{ icon: Plus }}
>
Add item
</Button>
{/if}
</div>
<div class="mt-2 mr-4">
<Toggle
on:change={(e) => {
// Once the user has changed the input type, we should not change it back automatically
if (!hasIsListJsonChanged) {
hasIsListJsonChanged = true
}
{#if !displayHeader}
<div class="block mt-2.5 pl-2">
<Toggle
on:change={(e) => {
// Once the user has changed the input type, we should not change it back automatically
if (!hasIsListJsonChanged) {
hasIsListJsonChanged = true
}
evalValueToRaw()
isListJson = !isListJson
}}
checked={isListJson}
textClass="text-secondary"
size="xs"
options={{ right: 'json' }}
/>
</div>
evalValueToRaw()
isListJson = !isListJson
}}
checked={isListJson}
textClass="text-secondary"
size="xs"
options={{ left: 'json' }}
/>
</div>
{/if}
</div>
{:else if inputCat == 'dynamic'}
<DynamicInput name={label} {otherArgs} {helperScript} bind:value format={format ?? ''} />
@@ -952,7 +1022,7 @@
/>
{:else if inputCat == 'object' || inputCat == 'resource-object' || isListJson}
{#if oneOf && oneOf.length >= 2}
<div class="flex flex-col gap-2 w-full">
<div class="flex flex-col gap-2 w-full border rounded-md p-2">
{#if oneOf && oneOf.length >= 2}
<ToggleButtonGroup
selected={oneOfSelected}
@@ -992,70 +1062,70 @@
{@const obj = oneOf[objIdx]}
{#if obj && obj.properties && Object.keys(obj.properties).length > 0}
{#key redraw}
<div class="py-4 pr-2 pl-6 border rounded w-full">
{#if orderEditable}
<SchemaFormDnd
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
{disabled}
{prettifyHeader}
bind:schema={
() => ({
properties: obj.properties ?? {},
order: obj.order,
$schema: '',
required: obj.required ?? [],
type: 'object'
}),
() => {
dispatch('nestedChange')
}
}
bind:args={value}
hiddenArgs={[
oneOf?.find((o) => Object.keys(o.properties ?? {}).includes('kind'))
? 'kind'
: 'label'
]}
on:reorder={(e) => {
if (oneOf && oneOf[objIdx]) {
const keys = e.detail
oneOf[objIdx].order = keys
}
}}
on:nestedChange
{shouldDispatchChanges}
/>
{:else}
<SchemaForm
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
{disabled}
{prettifyHeader}
hiddenArgs={['label', 'kind']}
schema={{
properties: obj.properties,
{#if orderEditable}
<SchemaFormDnd
lightHeaderFont
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
{disabled}
{prettifyHeader}
bind:schema={
() => ({
properties: obj.properties ?? {},
order: obj.order,
$schema: '',
required: obj.required ?? [],
type: 'object'
}}
bind:args={
() => value,
(v) => {
value = { ...v, [tagKey]: oneOfSelected }
}
}
{shouldDispatchChanges}
on:change={() => {
}),
() => {
dispatch('nestedChange')
}}
on:nestedChange
/>
{/if}
</div>
}
}
bind:args={value}
hiddenArgs={[
oneOf?.find((o) => Object.keys(o.properties ?? {}).includes('kind'))
? 'kind'
: 'label'
]}
on:reorder={(e) => {
if (oneOf && oneOf[objIdx]) {
const keys = e.detail
oneOf[objIdx].order = keys
}
}}
on:nestedChange
{shouldDispatchChanges}
/>
{:else}
<SchemaForm
lightHeaderFont
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
{disabled}
{prettifyHeader}
hiddenArgs={['label', 'kind']}
schema={{
properties: obj.properties,
order: obj.order,
$schema: '',
required: obj.required ?? [],
type: 'object'
}}
bind:args={
() => value,
(v) => {
value = { ...v, [tagKey]: oneOfSelected }
}
}
{shouldDispatchChanges}
on:change={() => {
dispatch('nestedChange')
}}
on:nestedChange
/>
{/if}
{/key}
{:else if disabled}
<textarea disabled></textarea>
@@ -1102,9 +1172,10 @@
{/if}
</div>
{:else if properties && Object.keys(properties).length > 0 && inputCat !== 'list'}
<div class={hideNested ? 'hidden' : 'py-4 pr-2 pl-6 border rounded-md w-full'}>
<div class={hideNested ? 'hidden' : 'px-2 pt-2 border rounded-md w-full'}>
{#if orderEditable}
<SchemaFormDnd
lightHeaderFont
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
@@ -1135,6 +1206,7 @@
/>
{:else}
<SchemaForm
lightHeaderFont
{nestedClasses}
{onlyMaskPassword}
{disablePortal}
@@ -1185,8 +1257,8 @@
/>
{/await}
{/if}
{#if inputCat == 'list'}
<div class="block">
{#if inputCat == 'list' && !displayHeader}
<div class="block mt-2.5 pl-2">
<Toggle
on:change={(e) => {
isListJson = !isListJson
@@ -1194,7 +1266,7 @@
checked={isListJson}
textClass="text-secondary"
size="xs"
options={{ right: 'json' }}
options={{ left: 'json' }}
/>
</div>
{/if}
@@ -1215,6 +1287,7 @@
dispatch('blur')
}}
enumLabels={extra['enumLabels']}
selectClass="min-h-10"
/>
</div>
{:else if inputCat == 'date'}
@@ -1323,12 +1396,7 @@
use:autosize
onkeydown={onKeyDown}
{disabled}
class={twMerge(
'w-full',
valid
? ''
: 'border border-red-700 border-opacity-30 focus:border-red-700 focus:border-opacity-3'
)}
class={twMerge('w-full', inputBaseClass, inputBorderClass({ error: !!error }))}
placeholder={placeholder ?? defaultValue ?? ''}
bind:value
></textarea>
@@ -1339,7 +1407,7 @@
<button
class="absolute {password || extra?.['password'] == true
? 'right-16 top-1.5'
: 'right-1 top-1'} 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"
: 'right-1 top-[7px]'} 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"
onclick={() => {
pickForField = label
itemPicker?.openDrawer?.()
@@ -1357,14 +1425,20 @@
{@render actions?.()}
</div>
{#if !compact || (error && error != '')}
<div class="text-right text-xs text-red-600 dark:text-red-400">
{#if disabled || error === ''}
&nbsp;
{:else}
{error}
{/if}
{#if description}
<div class={twMerge('text-2xs italic py-1 text-hint', css?.description?.class)}>
<pre class="font-main whitespace-normal">{description}</pre>
</div>
{/if}
{#if !compact || (error && error != '')}
{#if disabled || error === ''}
&nbsp;
{:else}
<div class="text-right text-xs text-red-600 dark:text-red-400">
{error}
</div>
{/if}
{:else if !noMargin}
<div class="mb-2"></div>
{/if}
@@ -1376,10 +1450,4 @@
-webkit-appearance: none !important;
margin: 0;
}
/* Firefox */
input[type='number'] {
-moz-appearance: textfield !important;
appearance: textfield !important;
}
</style>
@@ -10,6 +10,7 @@
import type { SchemaProperty } from '$lib/common'
import Toggle from './Toggle.svelte'
import { tick } from 'svelte'
import Select from './select/Select.svelte'
interface Props {
canEditResourceType?: boolean
@@ -54,39 +55,44 @@
{#if canEditResourceType || originalType == 'string[]' || originalType == 'object[]'}
<Label label="Items type">
<select
bind:value={selected}
onchange={() => {
if (selected == 'enum') {
itemsType = { type: 'string', enum: [] }
} else if (selected == 'string') {
itemsType = { type: 'string' }
} else if (selected == 'number') {
itemsType = { type: 'number' }
} else if (selected == 'object') {
itemsType = { ...itemsType, type: 'object' }
} else if (selected == 'bytes') {
itemsType = { type: 'string', contentEncoding: 'base64' }
} else if (selected == 'resource') {
itemsType = { type: 'resource', resourceType: itemsType?.resourceType }
} else if (selected == 's3object') {
itemsType = { type: 'object', resourceType: 's3object' }
} else {
itemsType = undefined
<Select
bind:value={
() => selected,
(v) => {
selected = v
if (selected == 'enum') {
itemsType = { type: 'string', enum: [] }
} else if (selected == 'string') {
itemsType = { type: 'string' }
} else if (selected == 'number') {
itemsType = { type: 'number' }
} else if (selected == 'object') {
itemsType = { ...itemsType, type: 'object' }
} else if (selected == 'bytes') {
itemsType = { type: 'string', contentEncoding: 'base64' }
} else if (selected == 'resource') {
itemsType = { type: 'resource', resourceType: itemsType?.resourceType }
} else if (selected == 's3object') {
itemsType = { type: 'object', resourceType: 's3object' }
} else {
itemsType = undefined
}
}
}}
id="array-type-narrowing"
>
<option value="string"> Items are strings</option>
<option value="enum">Items are strings from an enum</option>
{#if originalType != 'string[]'}
<option value="s3object">Items are S3 objects</option>
<option value="object"> Items are objects (JSON)</option>
<option value="resource"> Items are resources</option>
<option value="number">Items are numbers</option>
<option value="bytes">Items are bytes</option>
{/if}
</select>
}
items={[
{ value: 'string', label: 'Items are strings' },
{ value: 'enum', label: 'Items are strings from an enum' },
...(originalType != 'string[]'
? [
{ value: 's3object', label: 'Items are S3 objects' },
{ value: 'object', label: 'Items are objects (JSON)' },
{ value: 'resource', label: 'Items are resources' },
{ value: 'number', label: 'Items are numbers' },
{ value: 'bytes', label: 'Items are bytes' }
]
: [])
] as { value: string; label: string }[]}
/>
</Label>
{:else if itemsType?.resourceType}
<Label label="Resource type">
@@ -530,7 +530,7 @@
{:else}
<!-- WIP -->
{#if jsonEnabled && customUi?.jsonOnly != true}
<div class="w-full p-3 flex gap-4 justify-end items-center">
<div class="w-full px-3 flex gap-4 justify-end items-center">
{#if addPropertyInEditorTab}
<AddPropertyV2
bind:schema
@@ -549,8 +549,8 @@
label="JSON View"
size="xs"
options={{
right: 'JSON editor',
rightTooltip:
left: 'JSON editor',
leftTooltip:
'Arguments can be edited either using the wizard, or by editing their JSON Schema.'
}}
lightMode
@@ -8,6 +8,7 @@
autoheight?: boolean
lineNumbersWidth?: number
lineNumbersOffset?: number
showNumbers?: boolean
class?: string
fontSize?: number
}
@@ -18,6 +19,7 @@
lineNumbersWidth = 51,
lineNumbersOffset = 0,
class: className = '',
showNumbers = true,
fontSize = 14
}: Props = $props()
@@ -76,7 +78,9 @@
class="margin-view-overlays"
role="presentation"
aria-hidden="true"
style="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: {lineNumbersWidth}px; height: 4893px;"
style="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: {lineNumbersWidth}px; height: 4893px; display: {!showNumbers
? 'none'
: 'block'};"
>
{#each lines as _, i}
<div style="top:{lineHeight * i}px;height:{lineHeight}px;">
@@ -40,17 +40,15 @@
{/if}
{#if displayType}
{#if format && !format.startsWith('resource') && !format.startsWith('jsonschema-')}
<span class="text-xs italic ml-2 text-tertiary dark:text-indigo-400">
<span class="text-xs italic ml-2 text-hint dark:text-indigo-400">
{#if format && !format.startsWith('resource') && !format.startsWith('jsonschema-')}
{format}
</span>
{:else}
<span class="text-xs italic ml-2 text-tertiary dark:text-indigo-400">
{:else}
{type ?? 'any'}{contentEncoding && contentEncoding != ''
? `, encoding: ${contentEncoding}`
: ''}
</span>
{/if}
{/if}
</span>
{/if}
{#if !emptyString(simpleTooltip)}
@@ -2,9 +2,11 @@
import { Plug } from 'lucide-svelte'
import { Button } from './common'
import AnimatedButton from './common/button/AnimatedButton.svelte'
import { twMerge } from 'tailwind-merge'
export let connecting: boolean
export let id: undefined | string = undefined
export let wrapperClasses = ''
</script>
<AnimatedButton animate={connecting} baseRadius="6px" animationDuration="2s" marginWidth="2px">
@@ -12,10 +14,14 @@
variant="border"
color="light"
size="xs2"
btnClasses={connecting ? 'text-blue-500' : 'text-primary'}
btnClasses={twMerge(
connecting ? 'text-blue-500' : 'text-tertiary',
'group/plug-btn overflow-clip flex p-0'
)}
on:click
{...id ? { id } : {}}
{wrapperClasses}
>
<Plug size={16} /> &rightarrow;
<Plug size={14} />
</Button>
</AnimatedButton>
@@ -23,7 +23,6 @@
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
import { tick } from 'svelte'
import { fade } from 'svelte/transition'
import { buildPrefixRegex } from './flows/previousResults'
import type VariableEditor from './VariableEditor.svelte'
import type ItemPicker from './ItemPicker.svelte'
@@ -39,6 +38,7 @@
import FlowPlugConnect from './FlowPlugConnect.svelte'
import { deepEqual } from 'fast-equals'
import S3ArrayHelperButton from './S3ArrayHelperButton.svelte'
import { inputBorderClass } from './text_input/TextInput.svelte'
interface Props {
schema: Schema | { properties?: Record<string, any>; required?: string[] }
@@ -470,17 +470,9 @@
)
</script>
{#if arg != undefined && !hidden}
<div
class={twMerge(
'pl-2 pt-2 pb-2 ml-2 relative hover:bg-surface hover:shadow-md transition-all duration-200',
$propPickerConfig?.propName == argName
? 'bg-surface border-l-4 border-blue-500 shadow-md rounded-l-md z-50 '
: 'hover:rounded-md',
className
)}
>
<div class="flex flex-row justify-between gap-1 pb-1 px-2">
{#if arg != undefined}
<div class={twMerge('pt-2 pb-2 relative group', className)}>
<div class="flex flex-row justify-between gap-1 pb-1">
<div class="flex flex-wrap grow">
<FieldHeader
label={argName}
@@ -496,7 +488,7 @@
{#if isStaticTemplate(inputCat)}
<div>
<span
class="bg-blue-100 text-blue-800 text-sm font-medium mr-2 px-2.5 !py-0.5 rounded ml-2 {propertyType ==
class="border border-blue-100 text-blue-500 text-2xs font-medium mr-2 px-1 !py-[1px] rounded ml-2 {propertyType ==
'static' && arg.type === 'javascript'
? 'visible'
: 'invisible'}"
@@ -507,7 +499,9 @@
{/if}
</div>
{#if !noDynamicToggle}
<div class="flex flex-row gap-x-2 gap-y-1 flex-wrap z-10 items-center">
<div
class="flex flex-row gap-x-2 z-10 absolute right-0 group-hover:bg-surface transition-colors"
>
{#if enableAi}
<StepInputGen
bind:this={stepInputGen}
@@ -536,8 +530,40 @@
}}
{pickableProperties}
{argName}
btnClass={twMerge(
'h-6 min-w-8 px-2',
'group-hover:opacity-100 transition-opacity',
!connecting ? 'opacity-0' : ''
)}
/>
{/if}
{#if propPickerWrapperContext}
<FlowPlugConnect
wrapperClasses={twMerge(
connecting ? 'h-5 w-7' : 'h-6 w-8',
'group-hover:opacity-100 transition-opacity p-0',
!connecting ? 'opacity-0' : ''
)}
id="flow-editor-plug"
{connecting}
on:click={() => {
if (
$propPickerConfig?.propName == argName &&
$propPickerConfig?.insertionMode == 'connect'
) {
clearFocus()
} else {
focusProp?.(argName, 'connect', (path) => {
connectProperty(path)
dispatch('change', { argName })
return true
})
}
}}
/>
{/if}
<div>
<ToggleButtonGroup
selected={propertyType}
@@ -593,19 +619,18 @@
propertyType = 'static'
}
}}
class="h-6"
>
{#snippet children({ item })}
{#if isStaticTemplate(inputCat)}
<ToggleButton
tooltip={`Write text or surround javascript with \`\$\{\` and \`\}\`. Use \`results\` to connect to another node\'s output.`}
light
value="static"
size="xs2"
label={'${}'}
{item}
/>
{:else}
<ToggleButton small label="Static" value="static" {item} />
<ToggleButton small label="static" value="static" {item} />
{/if}
{#if codeInjectionDetected && propertyType == 'static'}
@@ -634,27 +659,6 @@
{/snippet}
</ToggleButtonGroup>
</div>
{#if propPickerWrapperContext && inputCat !== 'dynamic'}
<FlowPlugConnect
id="flow-editor-plug"
{connecting}
on:click={() => {
if (
$propPickerConfig?.propName == argName &&
$propPickerConfig?.insertionMode == 'connect'
) {
clearFocus()
} else {
focusProp?.(argName, 'connect', (path) => {
connectProperty(path)
dispatch('change', { argName })
return true
})
}
}}
/>
{/if}
</div>
{/if}
</div>
@@ -674,12 +678,7 @@
<div class="relative flex flex-row items-top gap-2 justify-between">
<div class="min-w-0 grow">
{#if isStaticTemplate(inputCat) && propertyType == 'static' && !noDynamicToggle}
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs italic pb-1 text-secondary">
<pre class="font-main">{schema.properties[argName].description}</pre>
</div>
{/if}
<div class="mt-2 min-h-[28px]">
<div class="min-h-[28px]">
{#if arg}
<TemplateEditor
bind:this={monacoTemplate}
@@ -694,8 +693,14 @@
dispatch('change', { argName, arg })
}}
loadAsync
class="bg-surface-secondary"
/>
{/if}
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs italic py-1 text-hint">
<pre class="font-main">{schema.properties[argName].description}</pre>
</div>
{/if}
</div>
{:else if (propertyType === undefined || propertyType == 'static') && schema?.properties?.[argName]}
<ArgInput
@@ -743,23 +748,30 @@
transform?.type === 'static' ? transform.value : transform?.expr
])
)}
/>
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
{connecting}
onClick={() =>
switchToJsAndConnect((path) => appendPathToArrayExpr(arg.expr, path))}
/>
{/if}
>
{#snippet innerBottomSnippet()}
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
{connecting}
onClick={() =>
switchToJsAndConnect((path) => appendPathToArrayExpr(arg.expr, path))}
/>
{/if}
{/snippet}
</ArgInput>
{:else if arg.expr != undefined}
<div class="border mt-2">
<div
class={`bg-surface-secondary rounded-md min-h-[2.5rem] flex flex-col pl-4 ${inputBorderClass({ forceFocus: focused })}`}
>
<SimpleEditor
bind:this={monaco}
bind:code={arg.expr}
{extraLib}
lang="javascript"
shouldBindKey={false}
renderLineHighlight="none"
hideLineNumbers
fakeMonacoPlaceholderClass="mt-2"
on:focus={() => {
focused = true
focusProp?.(argName, 'insert', (path) => {
@@ -778,12 +790,10 @@
/>
<!-- <input type="text" bind:value={arg.expr} /> -->
</div>
{#if !hideHelpButton}
<DynamicInputHelpBox />
{/if}
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
class="mt-2"
{connecting}
onClick={() =>
focusProp?.(argName, 'connect', (path) => {
@@ -793,6 +803,10 @@
/>
{/if}
{#if !hideHelpButton}
<DynamicInputHelpBox />
{/if}
<div class="mb-2"></div>
{:else}
Not recognized input type {argName} ({arg.expr}, {propertyType})
@@ -807,29 +821,6 @@
>
{/if}
</div>
{#if $propPickerConfig?.propName == argName}
<div
class="text-blue-500 absolute top-2 lg:-right-2.5 -right-1"
in:fade={{ duration: 200 }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="24 24 12 12 24 0" />
</svg>
</div>
{:else}
<div class="w-0"></div>
{/if}
</div>
</div>
</div>
@@ -11,6 +11,7 @@
import ItemPicker from './ItemPicker.svelte'
import VariableEditor from './VariableEditor.svelte'
import { Plus } from 'lucide-svelte'
import ResizeTransitionWrapper from './common/ResizeTransitionWrapper.svelte'
interface Props {
schema: Schema | { properties?: Record<string, any> }
@@ -80,9 +81,9 @@
})
</script>
<div class="w-full {clazz}">
<div class="w-full mb-6 {clazz}">
{#if enableAi}
<div class="px-0.5 pt-0.5">
<div class="mt-2">
<StepInputsGen
{pickableProperties}
argNames={keys
@@ -101,7 +102,7 @@
{#if keys.length > 0}
{#each keys as argName, index (argName)}
{#if (!filter || filter.includes(argName)) && Object.keys(schema.properties ?? {}).includes(argName)}
<div class="pt-2 relative">
<ResizeTransitionWrapper class="mt-2 relative" innerClass="w-full" vertical>
<InputTransformForm
{previousModuleId}
bind:arg={args[argName]}
@@ -122,7 +123,7 @@
Object.entries(args ?? {}).filter(([key]) => key !== argName)
)}
/>
</div>
</ResizeTransitionWrapper>
{/if}
{/each}
{:else}
+13 -4
View File
@@ -7,6 +7,8 @@
import { createEventDispatcher } from 'svelte'
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
import Button from './common/button/Button.svelte'
import { twMerge } from 'tailwind-merge'
import { inputBorderClass } from './text_input/TextInput.svelte'
interface Props {
code: string | undefined
@@ -34,6 +36,7 @@
let tooBig = $derived(code && code?.length > 1000000)
let loadTooBigAnyway = $state(false)
let focused = $state(false)
const dispatch = createEventDispatcher()
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
@@ -66,12 +69,17 @@
</div>
{:else}
<div class="flex flex-col w-full">
<div class="border w-full">
<div
class={twMerge(
'w-full rounded-md bg-surface-secondary',
inputBorderClass({ error: !!error, forceFocus: focused })
)}
>
<SimpleEditor
{loadAsync}
{small}
on:focus
on:blur
on:focus={() => (dispatch('focus'), (focused = true))}
on:blur={() => (dispatch('blur'), (focused = false))}
bind:this={editor}
on:change
autoHeight
@@ -80,10 +88,11 @@
class={clazz}
{disabled}
{fixedOverflowWidgets}
renderLineHighlight="none"
/>
</div>
{#if error != ''}
<span class="text-red-600 text-xs">{error}</span>
<span class="text-red-600 text-xs mt-1">{error}</span>
{/if}
</div>
{/if}
@@ -150,20 +150,21 @@
nullable={schema.properties[argName].nullable}
title={schema.properties[argName].title}
placeholder={schema.properties[argName].placeholder}
/>
{/if}
{#if stepsInputArgs?.isArgManuallySet(mod.id, argName)}
<div class="pt-6 mt-0.5">
<Button
on:click={() => {
plugIt(argName)
}}
size="sm"
variant="border"
color="light"
title="Re-evaluate input step"><RefreshCw size={14} /></Button
>
</div>
>
{#snippet fieldHeaderActions()}
{#if stepsInputArgs?.isArgManuallySet(mod.id, argName)}
<Button
on:click={() => {
plugIt(argName)
}}
size="xs2"
variant="contained"
color="light"
title="Re-evaluate input step"><RefreshCw size={12} /></Button
>
{/if}
{/snippet}
</ArgInput>
{/if}
</div>
{/if}
@@ -3,6 +3,8 @@
import Toggle from './Toggle.svelte'
import Tooltip from './Tooltip.svelte'
import { selectOptions } from './apps/editor/component'
import Select from './select/Select.svelte'
import TextInput from './text_input/TextInput.svelte'
interface Props {
min: number | undefined
@@ -44,7 +46,11 @@
options={{ right: 'Enabled' }}
size="xs"
/>
{/snippet} <input type="number" bind:value={min} disabled={!minChecked} />
{/snippet}
<TextInput
inputProps={{ type: 'number', disabled: !minChecked }}
bind:value={() => min?.toString(), (v) => (min = v ? parseInt(v) : undefined)}
/>
</Label>
<Label label="Max" class="w-full col-span-1 ">
@@ -68,31 +74,41 @@
size="xs"
/>
{/snippet}
<input type="number" bind:value={max} disabled={!maxChecked} />
<TextInput
inputProps={{ type: 'number', disabled: !maxChecked }}
bind:value={() => max?.toString(), (v) => (max = v ? parseInt(v) : undefined)}
/>
</Label>
</div>
<div class="grid grid-cols-3 gap-4">
<Label label="Currency" class="w-full col-span-2">
<div class="flex gap-2">
<Label label="Currency" class=" col-span-2">
{#snippet header()}
<Tooltip light small>
Select a currency to display the number in. If a currency is selected, you can also select
a locale to format the number according to that locale.
</Tooltip>
{/snippet}
<select bind:value={currency}>
<option value={undefined}> No currency </option>
{#each selectOptions.currencyOptions as c}
<option value={c}>{c}</option>
{/each}
</select>
<Select
bind:value={
() => currency,
(v) => {
currency = v
if (!v) currencyLocale = undefined
}
}
items={selectOptions.currencyOptions.map((c) => ({ label: c, value: c }))}
placeholder="No currency"
clearable
/>
</Label>
<Label label="Currency locale" class="w-full">
<select bind:value={currencyLocale} disabled={!currency}>
<option value={undefined}> No locale </option>
{#each selectOptions.localeOptions as c}
<option value={c}>{c}</option>
{/each}
</select>
<Select
bind:value={currencyLocale}
items={selectOptions.localeOptions.map((c) => ({ label: c, value: c }))}
placeholder="No locale"
disabled={!currency}
clearable
/>
</Label>
</div>
</div>
@@ -6,11 +6,13 @@
import ResourceEditorDrawer from './ResourceEditorDrawer.svelte'
import { Button } from './common'
import { Pen, Plus, RotateCw } from 'lucide-svelte'
import { Loader2, Pen, Plus, RotateCw } from 'lucide-svelte'
import { sendUserToast } from '$lib/toast'
import Select from './select/Select.svelte'
import DbManagerDrawer from './DBManagerDrawer.svelte'
import ExploreAssetButton, { assetCanBeExplored } from './ExploreAssetButton.svelte'
import { twMerge } from 'tailwind-merge'
import DropdownV2 from './DropdownV2.svelte'
interface Props {
initialValue?: string | undefined
@@ -24,6 +26,7 @@
expressOAuthSetup?: boolean
defaultValues?: Record<string, any> | undefined
placeholder?: string | undefined
selectInputClass?: string
onClear?: () => void
excludedValues?: string[]
}
@@ -40,6 +43,7 @@
expressOAuthSetup = false,
defaultValues = undefined,
placeholder = undefined,
selectInputClass = '',
onClear = undefined,
excludedValues = undefined
}: Props = $props()
@@ -176,91 +180,102 @@
}}
/>
<!-- {JSON.stringify({ value, collection })} -->
<div class="flex flex-col w-full items-start min-h-9">
<div class="flex flex-col w-full items-start min-h-10">
<div class="flex flex-row w-full items-center">
{#if collection?.length > 0}
<Select
{disabled}
{disablePortal}
bind:value={
() => value,
(v) => {
value = v
valueType = collection.find((x) => x?.value == v)?.type
}
<Select
{disabled}
{disablePortal}
bind:value={
() => value,
(v) => {
value = v
valueType = collection.find((x) => x?.value == v)?.type
}
onClear={() => {
initialValue = undefined
value = undefined
valueType = undefined
onClear?.()
}}
items={collection}
clearable
class="text-clip grow min-w-0"
placeholder={placeholder ?? `${resourceType ?? 'any'} resource`}
/>
{:else if !loading}
<div class="text-2xs text-tertiary mr-2">0 found</div>
{/if}
{#if !loading}
<div class="mx-0.5"></div>
{#if value && value != ''}
}
onClear={() => {
initialValue = undefined
value = undefined
valueType = undefined
onClear?.()
}}
items={collection}
clearable
class="text-clip grow min-w-0"
inputClass={twMerge('min-h-10', selectInputClass)}
placeholder={placeholder ?? `${resourceType ?? 'any'} resource`}
itemLabelWrapperClasses="flex-1"
itemButtonWrapperClasses="flex"
>
{#snippet endSnippet({ item, close })}
<Button
{disabled}
color="light"
variant="contained"
size="sm"
btnClasses="w-8 px-0.5 py-1.5"
on:click={() => resourceEditor?.initEdit?.(value ?? '')}
size="xs3"
btnClasses="w-8 px-0.5 py-1.5 bg-transparent hover:bg-surface-secondary"
wrapperClasses="-mr-2 pl-1"
on:click={() => (resourceEditor?.initEdit?.(item.value ?? ''), close())}
startIcon={{ icon: Pen }}
iconOnly
/>
{/if}
{#if resourceType?.includes(',')}
{#each resourceType.split(',') as rt}
{/snippet}
{#snippet bottomSnippet({ close })}
<div class="flex bg-surface border-t divide-x">
{#if resourceType?.includes(',')}
<DropdownV2
enableFlyTransition
items={resourceType?.split(',').map((rt) => ({
displayName: `${rt} resource`,
icon: Plus,
action: () => (appConnect?.open?.(rt), close())
})) ?? []}
>
{#snippet buttonReplacement()}
<Button
{disabled}
color="light"
variant="contained"
wrapperClasses="flex-1"
btnClasses="rounded-none mt-0.5"
size="sm"
startIcon={{ icon: Plus }}
>
Add a resource
</Button>
{/snippet}
</DropdownV2>
{:else}
<Button
{disabled}
color="light"
variant="contained"
wrapperClasses="flex-1"
btnClasses="rounded-none"
size="sm"
on:click={() => (appConnect?.open?.(resourceType), close())}
startIcon={{ icon: Plus }}
>
Add a {resourceType} resource
</Button>
{/if}
<Button
{disabled}
color="light"
variant="contained"
color="light"
btnClasses="rounded-none"
size="sm"
btnClasses="w-8 px-0.5 py-1.5"
on:click={() => appConnect?.open?.(rt)}
startIcon={{ icon: Plus }}>{rt}</Button
>
{/each}
{:else}
<Button
{disabled}
color="light"
variant="border"
size="sm"
on:click={() => appConnect?.open?.(resourceType)}
startIcon={{ icon: Plus }}
iconOnly={collection?.length > 0}
>{#if collection?.length == 0}
Add a {resourceType} resource
{/if}</Button
>
<div class="mx-0.5"></div>
{/if}
{/if}
<Button
variant="contained"
color="light"
btnClasses="w-8 px-0.5 py-1.5"
size="sm"
on:click={() => {
loadResources(resourceType)
}}
startIcon={{ icon: RotateCw }}
iconOnly
/>
on:click={() => {
loadResources(resourceType)
}}
startIcon={loading ? { icon: Loader2, classes: 'animate-spin' } : { icon: RotateCw }}
iconOnly
/>
</div>
{/snippet}
</Select>
</div>
{#if showSchemaExplorer && value && assetCanBeExplored({ kind: 'resource', path: value }, { resource_type: resourceType })}
<ExploreAssetButton
class="mt-1"
_resourceMetadata={{ resource_type: resourceType }}
asset={{ kind: 'resource', path: value }}
{dbManagerDrawer}
@@ -6,15 +6,27 @@
label?: string
onClick: () => void
connecting?: boolean
class?: string
}
let { label = 'Add object from an expression', onClick, connecting = false }: Props = $props()
let {
label = 'Add object from an expression',
onClick,
connecting = false,
class: className = ''
}: Props = $props()
</script>
{#if !connecting}
<div class="mt-2 mb-2">
<Button variant="border" color="light" size="xs" startIcon={{ icon: Plug }} onclick={onClick}>
{label}
</Button>
</div>
<Button
variant="border"
color="light"
size="xs"
btnClasses="font-normal text-tertiary"
startIcon={{ icon: Plug }}
onclick={onClick}
wrapperClasses={className}
>
{label}
</Button>
{/if}
+16 -5
View File
@@ -19,6 +19,8 @@
import { dragHandleZone, type Options as DndOptions } from '@windmill-labs/svelte-dnd-action'
import type { SchemaDiff } from '$lib/components/schema/schemaUtils.svelte'
import type { ComponentCustomCSS } from './apps/types'
import ResizeTransitionWrapper from './common/ResizeTransitionWrapper.svelte'
import { twMerge } from 'tailwind-merge'
interface Props {
schema: Schema | any
@@ -56,6 +58,7 @@
displayType?: boolean
appPath?: string | undefined
className?: string
lightHeaderFont?: boolean
computeS3ForceViewerPolicies?:
| (() =>
| {
@@ -106,6 +109,7 @@
displayType = true,
appPath = undefined,
className = '',
lightHeaderFont = false,
computeS3ForceViewerPolicies = undefined,
workspace = undefined,
actions: actions_render = undefined
@@ -269,10 +273,15 @@
{#if keys.length > 0 && args}
{#each fields as item, i (item.id)}
{@const argName = item.value}
<div
class={typeof diff[argName] === 'object' && diff[argName].diff !== 'same'
? 'bg-red-300 dark:bg-red-800 rounded-md'
: ''}
<ResizeTransitionWrapper
vertical
class={twMerge(
typeof diff[argName] === 'object' &&
diff[argName].diff !== 'same' &&
'bg-red-300 dark:bg-red-800 rounded-md',
'relative'
)}
innerClass="w-full"
>
<!-- svelte-ignore a11y_click_events_have_key_events -->
{#if !hiddenArgs.includes(argName) && keys.includes(argName)}
@@ -280,6 +289,7 @@
{@const formerProperty = diff[argName].oldSchema}
<div class="px-2">
<ArgInput
{lightHeaderFont}
{disablePortal}
{resourceTypes}
{prettifyHeader}
@@ -342,6 +352,7 @@
{JSON.stringify(args?.[argName])} -->
{#if !hidden[argName]}
<ArgInput
{lightHeaderFont}
on:change={() => {
dispatch('change')
}}
@@ -443,7 +454,7 @@
{/if}
</div>
{/if}
</div>
</ResizeTransitionWrapper>
{/each}
{:else if !shouldHideNoInputs}
<div class="text-secondary text-sm">No inputs</div>
@@ -537,7 +537,7 @@
<SplitPanesWrapper>
<Splitpanes class="!overflow-visible">
<Pane bind:size={codePanelSize} minSize={10} class="!overflow-visible">
<div class="h-full !overflow-visible bg-gray-50 dark:bg-[#272D38] relative">
<div class="h-full !overflow-visible bg-surface dark:bg-[#272D38] relative">
<div class="absolute top-2 right-4 z-10 flex flex-row gap-2">
{#if assets?.length}
<AssetsDropdownButton {assets} />
@@ -85,10 +85,12 @@
allowVim = false,
tailwindClasses = [],
class: className = '',
fakeMonacoPlaceholderClass = '',
loadAsync = false,
key,
disabled = false,
minHeight = 1000
minHeight = 1000,
renderLineHighlight = 'line'
}: {
lang: string
code?: string
@@ -110,11 +112,13 @@
allowVim?: boolean
tailwindClasses?: string[]
class?: string
fakeMonacoPlaceholderClass?: string
loadAsync?: boolean
initialCursorPos?: IPosition
key?: string
disabled?: boolean
minHeight?: number
renderLineHighlight?: 'all' | 'line' | 'gutter' | 'none'
} = $props()
const dispatch = createEventDispatcher()
@@ -332,6 +336,11 @@
$relativeLineNumbers
),
model,
padding: {
bottom: 8,
top: 8
},
renderLineHighlight,
lineDecorationsWidth: 6,
lineNumbersMinChars: 2,
fontSize: fontSize,
@@ -602,9 +611,11 @@
<FakeMonacoPlaceHolder
{code}
autoheight
lineNumbersWidth={(23 * fontSize) / 14}
lineNumbersWidth={hideLineNumbers ? 0 : (23 * fontSize) / 14}
lineNumbersOffset={fontSize == 14 ? -8 : -11}
{fontSize}
showNumbers={!hideLineNumbers}
class={fakeMonacoPlaceholderClass}
/>
{/if}
@@ -11,6 +11,7 @@
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
import RegexGen from './copilot/RegexGen.svelte'
import TextInput from './text_input/TextInput.svelte'
interface Props {
pattern: string | undefined
@@ -326,7 +327,10 @@
{:else if kind == 'none'}
{#if !noExtra}
<Label label="Min textarea rows">
<input type="number" bind:value={minRows} />
<TextInput
inputProps={{ type: 'number' }}
bind:value={() => minRows?.toString(), (v) => (minRows = v ? parseInt(v) : undefined)}
/>
</Label>
{/if}
{:else if kind === 'base64'}
@@ -26,6 +26,7 @@
import EditorTheme from './EditorTheme.svelte'
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
import { setMonacoJsonOptions } from './monacoLanguagesOptions'
import { inputBorderClass } from './text_input/TextInput.svelte'
export const conf = {
wordPattern:
@@ -449,7 +450,14 @@
lineDecorationsWidth: 6,
lineNumbersMinChars: 2,
fontSize,
suggestOnTriggerCharacters: true
suggestOnTriggerCharacters: true,
renderLineHighlight: 'none',
lineNumbers: 'off',
padding: {
bottom: 8,
top: 8
}
})
} catch (e) {
console.error('Error loading monaco:', e)
@@ -498,10 +506,12 @@
editor.onDidFocusEditorText(() => {
dispatch('focus')
isFocus = true
})
editor.onDidBlurEditorText(() => {
dispatch('blur')
isFocus = false
updateCode()
})
@@ -597,6 +607,7 @@
editor?.focus()
}
let isFocus = false
let mounted = false
let loadTimeout: number | undefined = undefined
onMount(async () => {
@@ -650,19 +661,18 @@
{#if !editor}
<FakeMonacoPlaceHolder
autoheight
showNumbers={false}
{code}
lineNumbersWidth={23}
lineNumbersOffset={-8}
class="border template nonmain-editor rounded min-h-4 mx-0.5 overflow-clip"
lineNumbersWidth={14}
lineNumbersOffset={-20}
class="template nonmain-editor rounded-md min-h-4 bg-surface-secondary !py-[9px] overflow-clip"
/>
{/if}
<div
bind:this={divEl}
style="height: 18px;"
class="{$$props.class ??
''} border template nonmain-editor rounded min-h-4 mx-0.5 overflow-clip {!editor
? 'hidden'
: ''}"
style="height: 18px; padding-left: 8px;"
class="{inputBorderClass({ forceFocus: isFocus })} {$$props.class ??
''} template nonmain-editor rounded-md min-h-4 overflow-clip {!editor ? 'hidden' : ''}"
bind:clientWidth={width}
></div>
+12 -4
View File
@@ -43,8 +43,12 @@
{#if Boolean(options?.left)}
<span
class={twMerge(
'mr-2 font-medium duration-50 select-none',
bothOptions || textDisabled ? (checked ? 'text-disabled' : 'text-primary') : 'text-primary',
'mr-2 font-normal duration-50 select-none',
bothOptions || textDisabled
? checked
? 'text-disabled'
: 'text-tertiary'
: 'text-tertiary',
size === 'xs' || size === '2sm' ? 'text-xs' : size === '2xs' ? 'text-[0.5rem]' : 'text-sm',
textClass
)}
@@ -103,8 +107,12 @@
{#if Boolean(options?.right)}
<span
class={twMerge(
'ml-2 font-medium duration-50 select-none',
bothOptions || textDisabled ? (checked ? 'text-primary' : 'text-disabled') : 'text-primary',
'ml-2 font-normal duration-50 select-none',
bothOptions || textDisabled
? checked
? 'text-tertiary'
: 'text-disabled'
: 'text-tertiary',
size === 'xs' || size === '2sm' ? 'text-xs' : size === '2xs' ? 'text-xs' : 'text-sm',
textClass
)}
@@ -1,5 +1,6 @@
<script lang="ts">
import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
import { inputBaseClass, inputBorderClass } from '$lib/components/text_input/TextInput.svelte'
import { onMount, untrack } from 'svelte'
/* Forked from MIT LICENSE
@@ -208,7 +209,7 @@
bind:value
/>
<input
class="
class="{inputBaseClass} {inputBorderClass()}
{inputClasses?.formatted ?? DEFAULT_CLASS_FORMATTED}
{isNegativeAllowed && !isZero && !isNegative
? (inputClasses?.formattedPositive ?? DEFAULT_CLASS_FORMATTED_POSITIVE)
@@ -0,0 +1,46 @@
<script lang="ts">
import { twMerge } from 'tailwind-merge'
type Props = {
children: import('svelte').Snippet
innerClass?: string
class?: string
horizontal?: boolean
vertical?: boolean
}
let { children, innerClass, class: className = '', horizontal, vertical }: Props = $props()
let innerContainer: HTMLElement | null = $state(null)
let outerContainer: HTMLElement | null = $state(null)
let width: number | null = $state(null)
let height: number | null = $state(null)
let style = $derived.by(() => {
let s = 'transition: width 0.2s, height 0.2s; overflow: clip;'
if (width !== null) s += `width: ${width}px;`
if (height !== null) s += `height: ${height}px;`
return s
})
$effect(() => {
if (!innerContainer || !outerContainer) return
let observer = new ResizeObserver((entries) => {
for (const entry of entries) {
if (horizontal) width = entry.contentRect.width
if (vertical) height = entry.contentRect.height
}
})
observer.observe(innerContainer)
return () => {
if (innerContainer) observer.unobserve(innerContainer)
observer.disconnect()
}
})
</script>
<div bind:this={outerContainer} class={className} {style}>
<div class={twMerge('absolute', innerClass)} bind:this={innerContainer}>
{@render children()}
</div>
</div>
@@ -154,7 +154,7 @@
variant === 'border' ? 'border' : '',
ButtonType.FontSizeClasses[size],
ButtonType.SpacingClasses[spacingSize][variant],
'focus-visible:ring-2 font-semibold',
'focus-visible:ring-2 font-normal',
dropdownItems && dropdownItems.length > 0 ? 'rounded-l-md h-full' : 'rounded-md',
'justify-center items-center text-center whitespace-nowrap inline-flex gap-2',
btnClasses,
@@ -15,7 +15,7 @@
export let multiple = false
export let convertTo: ReadFileAs | undefined = undefined
export let hideIcon = false
export let iconSize = 36
export let iconSize = 24
export let returnFileNames = false
export let submittedText: string | undefined = undefined
export let defaultFile: string | string[] | undefined = undefined
@@ -187,10 +187,11 @@
<button
class={twMerge(
`relative center-center flex-col text-center font-medium text-tertiary
border border-dashed border-gray-400 hover:border-blue-500
`relative center-center flex flex-col gap-x-2 gap-y-1 justify-center items-center flex-wrap text-center font-normal text-hint text-xs rounded-md
bg-surface-secondary
border border-dashed border-transparent hover:border-blue-500
focus-within:border-blue-300 hover:bg-blue-50 dark:hover:bg-frost-900
duration-200 rounded-component p-1`,
duration-200 px-1 py-8`,
c
)}
on:dragover={handleDragOver}
@@ -209,7 +210,7 @@
{disabled}
>
{#if !hideIcon && !files}
<FileUp size={iconSize} class="mb-2" />
<FileUp size={iconSize} />
{/if}
{#if files}
<div class="w-full max-h-full overflow-auto px-6">
@@ -17,7 +17,8 @@
computeS3ForceViewerPolicies,
workspace,
editor = $bindable(),
appPath
appPath,
bottom
}: {
multiple: boolean
value: any
@@ -38,6 +39,7 @@
workspace: string | undefined
editor: SimpleEditor | undefined
appPath: string | undefined
bottom?: import('svelte').Snippet
} = $props()
let s3FileUploadRawMode: boolean = $state(false)
@@ -67,13 +69,7 @@
/>
{/if}
<div class="flex flex-col w-full gap-1">
<Toggle
class="flex justify-end"
bind:checked={s3FileUploadRawMode}
size="xs"
options={{ left: `Raw S3 object${multiple ? 's' : ''} input` }}
/>
<div class="flex flex-col w-full gap-1 relative">
{#if s3FileUploadRawMode}
{#await import('$lib/components/JsonEditor.svelte')}
<Loader2 class="animate-spin" />
@@ -135,7 +131,7 @@
variant="border"
color="light"
size="xs"
btnClasses="mt-1"
btnClasses="mt-1 font-normal text-tertiary"
on:click={() => {
s3FilePicker?.open?.(value)
}}
@@ -144,4 +140,12 @@
{multiple ? 'Add' : 'Choose'} an object from the catalog
</Button>
{/if}
{@render bottom?.()}
<Toggle
class="mt-1"
textClass="font-normal text-tertiary"
bind:checked={s3FileUploadRawMode}
size="xs"
options={{ right: `Raw S3 object${multiple ? 's' : ''} input` }}
/>
</div>
@@ -48,6 +48,7 @@
<div
use:clickOutside={{
eventToListenName: 'pointerdown',
stopPropagation: true,
onClickOutside: () => (open = false)
}}
>
@@ -30,10 +30,11 @@
{id}
{disabled}
class={twMerge(
'group rounded-md transition-all text-xs flex gap-1 flex-row items-center',
'group rounded-md transition-all text-xs font-normal flex gap-1 flex-row items-center border',
small ? 'px-1.5 py-0.5 text-2xs' : 'px-2 py-1',
light ? 'font-medium' : '',
'data-[state=on]:bg-surface data-[state=on]:shadow-md',
'data-[state=on]:bg-surface data-[state=off]:border-transparent data-[state=on]:border-gray-300 dark:data-[state=on]:border-gray-500',
'text-hint data-[state=on]:text-tertiary',
'bg-surface-secondary hover:bg-surface-hover',
disabled ? '!shadow-none' : '',
$$props.class
@@ -72,7 +72,7 @@
>
<div
class={twMerge(
'flex bg-surface-secondary rounded-md p-0.5 gap-1 h-full',
'flex bg-surface-secondary rounded-md h-full',
wrap ? 'flex-wrap' : '',
tabListClass
)}
@@ -18,6 +18,7 @@
item?: any | undefined
selected?: string | undefined
togglableItems: TogglableItem[]
class?: string
}
let {
@@ -27,7 +28,8 @@
id = undefined,
item = undefined,
selected = $bindable(undefined),
togglableItems
togglableItems,
class: className = ''
}: Props = $props()
let items = togglableItems.map((i) => ({
@@ -44,7 +46,7 @@
<Popover
disablePopup={true}
notClickable
class={twMerge('flex', disabled ? 'cursor-not-allowed' : 'cursor-pointer')}
class={twMerge('flex', disabled ? 'cursor-not-allowed' : 'cursor-pointer', className)}
disappearTimeout={0}
>
<div {id} class="flex">
@@ -27,6 +27,7 @@
export let pickableProperties: PickableProperties | undefined = undefined
export let argName: string
export let showPopup: boolean
export let btnClass = ''
let empty = false
$: empty =
@@ -211,10 +212,11 @@ Only return the expression without any wrapper.`
size="xs"
color="light"
btnClasses={twMerge(
'text-violet-800 dark:text-violet-400 bg-violet-100 dark:bg-gray-700 dark:hover:bg-surface-hover',
'text-violet-500 dark:text-violet-400 border border-violet-100 dark:border-gray-700 dark:hover:bg-surface-hover',
!loading && generatedContent.length > 0
? 'bg-green-100 text-green-800 hover:bg-green-100 dark:text-green-400 dark:bg-green-700 dark:hover:bg-green-700'
: ''
: '',
btnClass
)}
on:click={() => {
if (!loading && generatedContent.length > 0) {
@@ -178,6 +178,7 @@ input_name2: expression2
<Button
size="xs"
color="light"
wrapperClasses="flex-1 border rounded-md"
btnClasses={twMerge(
'text-violet-800 dark:text-violet-400',
!loading && Object.keys($generatedExprs || {}).length > 0
@@ -2,19 +2,19 @@
import Button from '$lib/components/common/button/Button.svelte'
import { ChevronDown } from 'lucide-svelte'
import { slide } from 'svelte/transition'
$: opened = false
</script>
<div class="text-xs flex flex-row-reverse mt-1">
<div class="text-xs flex flex-row-reverse">
<Button
on:click={() => {
opened = !opened
}}
color="light"
variant="divider"
size="xs2"
endIcon={{ icon: ChevronDown, classes: `rotate-0 duration-300 ${opened ? '!rotate-180' : ''}` }}
btnClasses="text-hint font-normal pt-1"
>
Help
</Button>
@@ -22,8 +22,7 @@
{#if opened}
<div
transition:slide|local
class="bg-surface-secondary border-l-4 text-secondary p-4 m-4"
class="bg-surface-secondary border-l-4 text-sm text-secondary p-4 mt-2"
role="alert"
id="dynamic-input-help-box"
>
@@ -548,7 +548,7 @@
></div>
{/if}
<InputTransformSchemaForm
class="px-1 xl:px-2"
class="px-2 xl:px-4"
bind:this={inputTransformSchemaForm}
pickableProperties={stepPropPicker.pickableProperties}
schema={flowStateStore.val[$selectedId]?.schema ?? {}}
@@ -16,6 +16,7 @@
import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte'
import { createEventDispatcher, onMount, untrack } from 'svelte'
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
import TextInput, { inputBaseClass, inputBorderClass } from '../text_input/TextInput.svelte'
interface Props {
description?: string
@@ -179,6 +180,7 @@
onkeydown={onKeyDown}
onchange={() => dispatch('change')}
placeholder="Field description"
class={twMerge(inputBorderClass(), inputBaseClass, 'w-full')}
></textarea>
</Label>
@@ -186,30 +188,31 @@
{#snippet header()}
<Tooltip light>Will be displayed in the UI instead of the field name.</Tooltip>
{/snippet}
<input
<TextInput
bind:value={title}
onchange={() => dispatch('change')}
onkeydown={onKeyDown}
placeholder="Field title"
inputProps={{ placeholder: 'Field title', onkeydown, onchange: () => dispatch('change') }}
/>
</Label>
<Label label="Placeholder">
{#snippet header()}
<Tooltip light>
Will be displayed in the input field when the field is empty. If not set, the default
value will be used. The placeholder is disabled depending on the field type, format, etc.
</Tooltip>
{/snippet}
{#if shouldDisplayPlaceholder(type, format, enum_, contentEncoding, pattern, extra)}
<Label label="Placeholder">
{#snippet header()}
<Tooltip light>
Will be displayed in the input field when the field is empty. If not set, the default
value will be used. The placeholder is disabled depending on the field type, format,
etc.
</Tooltip>
{/snippet}
<textarea
placeholder="Enter a placeholder"
rows="1"
bind:value={placeholder}
onchange={() => dispatch('change')}
disabled={!shouldDisplayPlaceholder(type, format, enum_, contentEncoding, pattern, extra)}
></textarea>
</Label>
<textarea
placeholder="Enter a placeholder"
rows="1"
bind:value={placeholder}
onchange={() => dispatch('change')}
class={twMerge(inputBorderClass(), inputBaseClass, 'w-full')}
></textarea>
</Label>
{/if}
{#if type == 'array'}
<ArrayTypeNarrowing
@@ -285,11 +288,3 @@
{@render children?.()}
</div>
</div>
<style>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
</style>
@@ -25,6 +25,7 @@
helperScript?: DynamicInput.HelperScript
className?: string
dndType?: string
lightHeaderFont?: boolean
}
let {
@@ -44,7 +45,8 @@
isValid = $bindable(true),
noVariablePicker = false,
className = '',
dndType = generateRandomString()
dndType = generateRandomString(),
lightHeaderFont
}: Props = $props()
$effect.pre(() => {
@@ -135,10 +137,11 @@
{shouldDispatchChanges}
bind:isValid
{noVariablePicker}
{lightHeaderFont}
>
{#snippet actions()}
{#if !disableDnd}
<div class="w-4 h-8 cursor-move ml-2 handle" aria-label="drag-handle" use:dragHandle>
<div class="w-4 h-8 cursor-move ml-2 handle mt-[9px]" aria-label="drag-handle" use:dragHandle>
<GripVertical size={16} />
</div>
{/if}
@@ -30,7 +30,7 @@
role="listitem"
class={twMerge(
allowClear ? 'pr-1' : 'pr-3',
'pl-3 min-h-6 bg-surface-secondary rounded-full flex items-center gap-0.5',
'pl-3 min-h-6 border bg-surface rounded-full flex items-center gap-0.5',
currentlyDraggingIndex !== undefined ? 'hover:opacity-20' : ''
)}
style={currentlyDraggingIndex === index
@@ -54,7 +54,7 @@
<span class="text-sm select-none">{item.label || item.value}</span>
{#if allowClear}
<CloseButton
class="text-tertiary"
class="text-hint bg-transparent"
small
on:close={(e) => (onRemove(item), e.stopPropagation())}
/>
@@ -7,6 +7,7 @@
import DraggableTags from './DraggableTags.svelte'
import { Search } from 'lucide-svelte'
import { twMerge } from 'tailwind-merge'
import TextInput, { inputBorderClass } from '../text_input/TextInput.svelte'
type Value = Item['value']
@@ -59,7 +60,7 @@
let filterText = $state<string>('')
let open = $state<boolean>(false)
let wrapperEl: HTMLDivElement | undefined = $state()
let searchInputEl: HTMLInputElement | undefined = $state()
let searchInputEl: TextInput | undefined = $state()
$effect(() => searchInputEl?.focus())
@@ -99,7 +100,8 @@
<div
bind:this={wrapperEl}
class={twMerge(
'relative min-h-8 flex items-center w-full bg-surface border border-gray-300 rounded-md text-tertiary',
'relative min-h-10 flex items-center w-full bg-surface-secondary text-tertiary rounded-md',
inputBorderClass({ forceFocus: open && !disabled }),
disabled ? 'pointer-events-none' : '',
open && !disabled ? 'open' : '',
disabled ? 'disabled' : '',
@@ -113,7 +115,9 @@
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
{#if value.length === 0}
<span class={twMerge('text-sm ml-2 h-full flex items-center flex-1', placeholderClass)}>
<span
class={twMerge('text-sm ml-4 h-full flex items-center flex-1 text-hint', placeholderClass)}
>
{placeholder}
</span>
{:else}
@@ -134,10 +138,10 @@
/>
</ul>
{/if}
{#if allowClear && !hideMainClearBtn}
{#if allowClear && !hideMainClearBtn && !!value?.length}
<CloseButton
noBg
class="mr-1 remove-all"
class="mr-1 remove-all bg-transparent text-hint"
small
on:close={(e) => (clearValue(), e.stopPropagation())}
/>
@@ -163,12 +167,14 @@
{#snippet header()}
{#if processedItems.length - value.length > 0 || onCreateItem}
<div class="mx-2 mb-1 mt-2 flex items-center relative">
<input
<TextInput
bind:this={searchInputEl}
bind:value={filterText}
onblur={(e) => (e.preventDefault(), searchInputEl?.focus())}
placeholder="Search"
class="!pr-7"
inputProps={{
onblur: (e) => (e.preventDefault(), searchInputEl?.focus()),
placeholder: 'Search...'
}}
class="!pr-7 !bg-surface"
/>
<Search size={16} class="absolute right-2 text-tertiary" />
</div>
@@ -7,6 +7,7 @@
import { getLabel, processItems, type ProcessedItem } from './utils.svelte'
import SelectDropdown from './SelectDropdown.svelte'
import { deepEqual } from 'fast-equals'
import { inputBaseClass, inputBorderClass } from '../text_input/TextInput.svelte'
type Value = Item['value']
@@ -23,19 +24,24 @@
inputClass = '',
disablePortal = false,
loading = false,
error = false,
autofocus,
RightIcon,
createText,
noItemsMsg,
open = $bindable(false),
id,
itemLabelWrapperClasses,
itemButtonWrapperClasses,
groupBy,
sortBy,
onFocus,
onBlur,
onClear,
onCreateItem,
startSnippet
startSnippet,
endSnippet,
bottomSnippet
}: {
items?: Item[]
value: Value | undefined
@@ -49,19 +55,24 @@
inputClass?: string
disablePortal?: boolean
loading?: boolean
error?: boolean
autofocus?: boolean
RightIcon?: any
createText?: string
noItemsMsg?: string
open?: boolean
id?: string
itemLabelWrapperClasses?: string
itemButtonWrapperClasses?: string
groupBy?: (item: Item) => string
sortBy?: (a: Item, b: Item) => number
onFocus?: () => void
onBlur?: () => void
onClear?: () => void
onCreateItem?: (value: string) => void
startSnippet?: Snippet<[{ item: ProcessedItem<Value> }]>
startSnippet?: Snippet<[{ item: ProcessedItem<Value>; close: () => void }]>
endSnippet?: Snippet<[{ item: ProcessedItem<Value>; close: () => void }]>
bottomSnippet?: Snippet<[{ close: () => void }]>
} = $props()
let disabled = $derived(_disabled || (loading && !value))
@@ -112,7 +123,7 @@
</div>
{:else if clearable && !disabled && value}
<div class="absolute z-10 right-2 h-full flex items-center">
<CloseButton class="text-secondary" noBg small on:close={clearValue} />
<CloseButton class="bg-transparent text-hint" noBg small on:close={clearValue} />
</div>
{:else if RightIcon}
<div class="absolute z-10 right-2 h-full flex items-center">
@@ -130,10 +141,12 @@
: (valueEntry?.label ?? getLabel({ value }) ?? placeholder)}
style={containerStyle}
class={twMerge(
'!bg-surface text-ellipsis',
inputBaseClass,
inputBorderClass({ error, forceFocus: open }),
'w-full',
open ? '' : 'cursor-pointer',
!loading && value ? '!placeholder-primary' : '',
(clearable || RightIcon) && !disabled && value ? '!pr-8' : '',
!loading && value ? 'placeholder-primary' : 'placeholder-hint',
(clearable || RightIcon) && !disabled && value ? 'pr-8' : '',
inputClass ?? ''
)}
autocomplete="off"
@@ -152,6 +165,10 @@
getInputRect={inputEl && (() => inputEl!.getBoundingClientRect())}
{listAutoWidth}
{noItemsMsg}
{itemLabelWrapperClasses}
{itemButtonWrapperClasses}
{startSnippet}
{endSnippet}
{bottomSnippet}
/>
</div>
@@ -4,6 +4,7 @@
import { untrack, type Snippet } from 'svelte'
import type { ProcessedItem } from './utils.svelte'
import { twMerge } from 'tailwind-merge'
import { slide } from 'svelte/transition'
let {
processedItems: _processedItems,
@@ -16,10 +17,14 @@
noItemsMsg = 'No items found',
class: className = '',
ulClass = '',
itemLabelWrapperClasses = '',
itemButtonWrapperClasses = '',
header,
getInputRect,
onSelectValue,
startSnippet
startSnippet,
endSnippet,
bottomSnippet
}: {
processedItems?: ProcessedItem<T>[]
value: T | undefined
@@ -31,10 +36,14 @@
noItemsMsg?: string
class?: string
ulClass?: string
itemLabelWrapperClasses?: string
itemButtonWrapperClasses?: string
header?: Snippet
getInputRect?: () => DOMRect
onSelectValue: (item: ProcessedItem<T>) => void
startSnippet?: Snippet<[{ item: ProcessedItem<T> }]>
startSnippet?: Snippet<[{ item: ProcessedItem<T>; close: () => void }]>
endSnippet?: Snippet<[{ item: ProcessedItem<T>; close: () => void }]>
bottomSnippet?: Snippet<[{ close: () => void }]>
} = $props()
let processedItems = $derived(
@@ -101,53 +110,63 @@
<ConditionalPortal condition={!disablePortal} name="select-dropdown-portal">
{#if open && !disabled}
<div
transition:slide={{ duration: 150 }}
class={twMerge(
disablePortal ? 'absolute' : 'fixed',
'flex flex-col z-[5001] max-h-64 overflow-y-auto bg-surface-secondary text-tertiary text-sm select-none border rounded-lg shadow-lg',
'z-[5001] rounded-md bg-surface-secondary text-tertiary text-sm select-none',
className
)}
style="{`top: ${dropdownPos.y}px; left: ${dropdownPos.x}px;`} {listAutoWidth
? `min-width: ${dropdownPos.width}px;`
: ''}"
bind:this={listEl}
>
{@render header?.()}
{#if processedItems?.length === 0}
<div class="py-8 px-4 text-center text-primary">{noItemsMsg}</div>
{/if}
<ul class={twMerge('flex-1 overflow-y-auto flex flex-col', ulClass)}>
{#each processedItems ?? [] as item, itemIndex}
{#if (item.__select_group && itemIndex === 0) || processedItems?.[itemIndex - 1]?.__select_group !== item.__select_group}
<li
class={twMerge(
'mx-4 pb-1 mb-2 text-xs font-semibold text-primary border-b',
itemIndex === 0 ? 'mt-3' : 'mt-6'
)}
>
{item.__select_group}
<div
bind:this={listEl}
class="flex flex-col max-h-64 border rounded-md shadow-lg overflow-clip"
>
{@render header?.()}
{#if processedItems?.length === 0}
<div class="py-8 px-4 text-center text-primary">{noItemsMsg}</div>
{/if}
<ul class={twMerge('flex-1 overflow-y-auto flex flex-col', ulClass)}>
{#each processedItems ?? [] as item, itemIndex}
{#if (item.__select_group && itemIndex === 0) || processedItems?.[itemIndex - 1]?.__select_group !== item.__select_group}
<li
class={twMerge(
'mx-4 pb-1 mb-2 text-xs font-semibold text-primary border-b',
itemIndex === 0 ? 'mt-3' : 'mt-6'
)}
>
{item.__select_group}
</li>
{/if}
<li>
<button
class={twMerge(
'py-2 px-4 w-full font-normal text-left text-primary',
itemIndex === keyArrowPos ? 'bg-surface-hover' : '',
item.value === value ? 'bg-surface-selected' : 'hover:bg-surface-hover',
itemButtonWrapperClasses
)}
onclick={(e) => {
e.stopImmediatePropagation()
onSelectValue(item)
}}
>
{@render startSnippet?.({ item, close: () => (open = false) })}
<span class={itemLabelWrapperClasses}>
{item.label || '\xa0'}
</span>
{@render endSnippet?.({ item, close: () => (open = false) })}
{#if item.subtitle}
<div class="text-xs text-tertiary">{item.subtitle}</div>
{/if}
</button>
</li>
{/if}
<li>
<button
class={twMerge(
'py-2 px-4 w-full font-normal text-left text-primary',
itemIndex === keyArrowPos ? 'bg-surface-hover' : '',
item.value === value ? 'bg-surface-selected' : 'hover:bg-surface-hover'
)}
onclick={(e) => {
e.stopImmediatePropagation()
onSelectValue(item)
}}
>
{@render startSnippet?.({ item })}
{item.label || '\xa0'}
{#if item.subtitle}
<div class="text-xs text-tertiary">{item.subtitle}</div>
{/if}
</button>
</li>
{/each}
</ul>
{/each}
</ul>
{@render bottomSnippet?.({ close: () => (open = false) })}
</div>
</div>
{/if}
</ConditionalPortal>
@@ -83,8 +83,8 @@
class={twMerge(
'group flex items-center px-2 py-2 font-light rounded-md h-8 gap-3 w-full',
lightMode
? 'text-primary data-[highlighted]:bg-surface-hover hover:bg-surface-hover'
: 'data-[highlighted]:bg-[#2A3648] hover:bg-[#2A3648] text-primary-inverse dark:text-primary',
? 'text-tertiary data-[highlighted]:bg-surface-hover hover:bg-surface-hover'
: 'data-[highlighted]:bg-[#2A3648] hover:bg-[#2A3648] text-tertiary dark:text-primary',
color ? 'border-4' : '',
'transition-all relative',
classNames
@@ -101,8 +101,8 @@
class={twMerge(
'flex-shrink-0',
lightMode
? 'text-primary group-hover:text-secondary'
: 'text-primary-inverse group-hover:text-secondary-inverse dark:group-hover:text-secondary dark:text-primary',
? 'text-tertiary group-hover:text-tertiary'
: 'text-tertiary group-hover:text-tertiary dark:group-hover:text-secondary dark:text-primary',
'transition-all',
iconClasses
)}
@@ -114,13 +114,13 @@
<span
class={twMerge(
'whitespace-pre truncate',
lightMode ? 'text-primary' : 'text-primary-inverse dark:text-primary',
lightMode ? 'text-primary' : 'text-tertiary dark:text-primary',
'transition-all',
classNames
)}
>
{label}
<span class="pl-2 text-xs dark:text-secondary light:text-secondary-inverse font-semibold">
<span class="pl-2 text-xs dark:text-secondary light:text-tertiary font-semibold">
{shortcut}
</span>
</span>
@@ -83,10 +83,10 @@
isSelected
? lightMode
? 'text-primary group-hover:text-secondary'
: 'text-frost-200 group-hover:text-white'
: 'text-tertiary group-hover:text-white'
: lightMode
? 'text-primary group-hover:text-secondary'
: 'text-gray-100 group-hover:text-white',
: 'text-tertiary group-hover:text-white',
'transition-all'
)}
/>
@@ -99,10 +99,10 @@
isSelected
? lightMode
? 'text-primary group-hover:text-secondary'
: 'text-frost-200 group-hover:text-white'
: 'text-tertiary group-hover:text-white'
: lightMode
? 'text-primary group-hover:text-secondary'
: 'text-gray-100 group-hover:text-white',
: 'text-tertiary group-hover:text-white',
'transition-all duration-75'
)}
>
@@ -359,7 +359,7 @@
}
]
: []),
...($workspaceStore?.startsWith("wm-fork")
...($workspaceStore?.startsWith('wm-fork')
? [
{
label: 'Delete Forked Workspace',
@@ -370,7 +370,7 @@
faIcon: undefined
}
]
: []),
: [])
],
disabled: $userStore?.operator
},
@@ -665,20 +665,20 @@
</div>
</ConfirmationModal>
{#if $workspaceStore?.startsWith("wm-fork-")}
<ConfirmationModal
open={deleteWorkspaceForkModal}
title="Delete forked workspace"
confirmationText="Remove"
on:canceled={() => {
deleteWorkspaceForkModal = false
}}
on:confirmed={() => {
deleteFork()
}}
>
<div class="flex flex-col w-full space-y-4">
<span>Are you sure you want to delete this workspace fork? (deleting {$workspaceStore})</span>
</div>
</ConfirmationModal>
{#if $workspaceStore?.startsWith('wm-fork-')}
<ConfirmationModal
open={deleteWorkspaceForkModal}
title="Delete forked workspace"
confirmationText="Remove"
on:canceled={() => {
deleteWorkspaceForkModal = false
}}
on:confirmed={() => {
deleteFork()
}}
>
<div class="flex flex-col w-full space-y-4">
<span>Are you sure you want to delete this workspace fork? (deleting {$workspaceStore})</span>
</div>
</ConfirmationModal>
{/if}
@@ -0,0 +1,55 @@
<script module lang="ts">
export function inputBorderClass({
error,
forceFocus
}: {
error?: boolean
forceFocus?: boolean
} = {}) {
return twMerge(
'transition-colors border',
forceFocus
? '!border-nord-900 dark:!border-nord-900'
: '!border-transparent focus:!border-nord-900 dark:focus:!border-nord-900 hover:!border-nord-400 dark:hover:!border-nord-300',
error
? '!border-red-300 focus:!border-red-400 hover:!border-red-500 dark:!border-red-400/40 dark:hover:!border-red-600/40'
: ''
)
}
export const inputBaseClass =
'rounded-md focus:ring-0 no-default-style text-sm text-tertiary !bg-surface-secondary disabled:!bg-surface-disabled disabled:!text-hint disabled:cursor-not-allowed shadow-none py-2 px-4 placeholder-hint'
</script>
<script lang="ts">
import type { HTMLInputAttributes } from 'svelte/elements'
import { twMerge } from 'tailwind-merge'
type Props = {
inputProps?: HTMLInputAttributes
value?: string
class?: string
error?: string
}
export function focus() {
inputEl?.focus()
}
let inputEl: HTMLInputElement | undefined = $state()
let { inputProps, value = $bindable(), class: className = '', error }: Props = $props()
</script>
<input
{...inputProps}
class={twMerge(
inputBaseClass,
'w-full',
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
inputBorderClass({ error: !!error }),
className
)}
bind:this={inputEl}
bind:value
/>
@@ -377,7 +377,7 @@
{/key}
{:else}
<span class="text-sm text-tertiary text-center mx-auto mt-2"
>{`Select a trigger from the ${useVerticalTriggerBar ? 'left toolbar' : 'table'} or a create a new one`}</span
>{`Select a trigger from the ${useVerticalTriggerBar ? 'left toolbar' : 'table'} or create a new one`}</span
>
{/if}
</div>
+5 -3
View File
@@ -231,7 +231,7 @@ export async function initializeVscode(caller?: string, htmlContainer?: HTMLElem
],
colors: {
'editor.foreground': '#D8DEE9',
'editor.background': '#272D38',
'editor.background': '#00000000',
'editor.selectionBackground': '#434C5ECC',
'editor.lineHighlightBackground': '#3B4252',
'editorCursor.foreground': '#D8DEE9',
@@ -244,8 +244,10 @@ export async function initializeVscode(caller?: string, htmlContainer?: HTMLElem
inherit: true,
rules: [],
colors: {
'editorLineNumber.foreground': '#999',
'editorGutter.background': '#F9FAFB'
'editor.background': '#FFFFFF00',
'editorLineNumber.foreground': '#C2C9D1',
'editorLineNumber.activeForeground': '#989DA5',
'editorGutter.background': '#FFFFFF00'
}
})
@@ -53,6 +53,7 @@
import { Menubar } from '$lib/components/meltComponents'
import { aiChatManager } from '$lib/components/copilot/chat/AIChatManager.svelte'
import AiChatLayout from '$lib/components/copilot/chat/AiChatLayout.svelte'
import { useIsDarkMode } from '$lib/components/DarkModeObserver.svelte'
interface Props {
children?: import('svelte').Snippet
}
@@ -387,6 +388,8 @@
}
}
})
let isDarkMode = useIsDarkMode()
</script>
<svelte:window bind:innerWidth />
@@ -423,7 +426,7 @@
>
<div
class={classNames(
'fixed inset-0 dark:bg-[#1e232e] bg-[#202125] dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 z-40 !dark',
'fixed inset-0 dark:bg-[#1e232e] bg-surface dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 z-40',
menuOpen ? 'opacity-100' : 'opacity-0'
)}
@@ -467,7 +470,7 @@
</svg>
</button>
</div>
<div class="dark:bg-[#1e232e] bg-[#202125] h-full !dark flex flex-col">
<div class="dark:bg-[#1e232e] bg-surface h-full flex flex-col">
<div class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-gray-200 w-40">
<WindmillIcon white={true} height="20px" width="20px" />
{#if $whitelabelNameStore}
@@ -521,13 +524,13 @@
<div
id="sidebar"
class={classNames(
'flex flex-col fixed inset-y-0 transition-all ease-in-out duration-200 shadow-md z-40 ',
'flex flex-col fixed inset-y-0 transition-all ease-in-out duration-200 z-40 ',
isCollapsed ? 'md:w-12' : 'md:w-40',
devOnly ? '!hidden' : ''
)}
>
<div
class="flex-1 flex flex-col min-h-0 h-screen shadow-lg dark:bg-[#1e232e] bg-[#202125] !dark"
class="flex-1 flex flex-col min-h-0 h-screen border-r dark:bg-[#1e232e] bg-surface"
>
<button
onclick={() => {
@@ -539,10 +542,10 @@
class:w-40={!isCollapsed}
>
<div class:mr-1={!isCollapsed}>
<WindmillIcon white={true} height="20px" width="20px" />
<WindmillIcon white={!isDarkMode} height="20px" width="20px" />
</div>
{#if !isCollapsed}
<div class="text-sm mt-0.5 text-white">
<div class="text-sm mt-0.5 text-tertiary">
{#if $whitelabelNameStore}{capitalize(
$whitelabelNameStore
)}{:else}Windmill{/if}
@@ -550,7 +553,7 @@
{/if}
</div>
</button>
<div class="px-2 py-4 border-y border-gray-700 flex flex-col gap-1">
<div class="px-2 py-4 border-y border-hint/40 flex flex-col gap-1">
<Menubar class="flex flex-col gap-1">
{#snippet children({ createMenu })}
<WorkspaceMenu {createMenu} {isCollapsed} />
@@ -597,7 +600,7 @@
<ArrowLeft
size={16}
class={classNames(
'flex-shrink-0 h-4 w-4 transition-all ease-in-out duration-200 text-white',
'flex-shrink-0 h-4 w-4 transition-all ease-in-out duration-200 text-tertiary',
isCollapsed ? 'rotate-180' : 'rotate-0'
)}
/>
@@ -615,7 +618,7 @@
<!-- Legacy menu -->
<div
class={classNames(
'fixed inset-0 dark:bg-[#1e232e] bg-[#202125] dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 !dark',
'fixed inset-0 dark:bg-[#1e232e] bg-surface dark:bg-opacity-75 bg-opacity-75 transition-opacity ease-linear duration-300 ',
'opacity-0 pointer-events-none'
)}
>
@@ -653,7 +656,7 @@
</svg>
</button>
</div>
<div class="dark:bg-[#1e232e] bg-[#202125] h-full !dark">
<div class="dark:bg-[#1e232e] bg-surface h-full">
<div
class="flex gap-x-2 flex-shrink-0 p-4 font-semibold text-gray-200 w-10"
class:w-40={!isCollapsed}
+10 -2
View File
@@ -14,6 +14,7 @@ const lightTheme = {
textPrimary: '#2d3748',
textSecondary: '#4a5568',
textTertiary: '#505c70',
textHint: '#A0A6B2',
textDisabled: '#a0aec0',
border: '#dddddd',
@@ -32,6 +33,7 @@ const darkTheme = {
textPrimary: '#EEEEEE',
textSecondary: '#C2C9D1',
textTertiary: '#A8AEB7',
textHint: '#989DA5',
textDisabled: '#989DA5',
border: '#3e4c60',
@@ -413,6 +415,7 @@ const config = {
primary: 'rgb(var(--color-text-primary) / <alpha-value>)',
secondary: 'rgb(var(--color-text-secondary) / <alpha-value>)',
tertiary: 'rgb(var(--color-text-tertiary) / <alpha-value>)',
hint: 'rgb(var(--color-text-hint) / <alpha-value>)',
disabled: 'rgb(var(--color-text-disabled) / <alpha-value>)',
'surface-inverse': 'rgb(var(--color-surface-inverse) / <alpha-value>)',
@@ -424,6 +427,7 @@ const config = {
'primary-inverse': 'rgb(var(--color-text-primary-inverse) / <alpha-value>)',
'secondary-inverse': 'rgb(var(--color-text-secondary-inverse) / <alpha-value>)',
'tertiary-inverse': 'rgb(var(--color-text-tertiary-inverse) / <alpha-value>)',
'hint-inverse': 'rgb(var(--color-text-hint-inverse) / <alpha-value>)',
'disabled-inverse': 'rgb(var(--color-text-disabled-inverse) / <alpha-value>)'
},
fontFamily: {
@@ -519,6 +523,7 @@ const config = {
'--color-text-primary': lightThemeRgb.textPrimary,
'--color-text-secondary': lightThemeRgb.textSecondary,
'--color-text-tertiary': lightThemeRgb.textTertiary,
'--color-text-hint': lightThemeRgb.textHint,
'--color-text-disabled': lightThemeRgb.textDisabled,
'--color-surface-inverse': darkThemeRgb.surface,
@@ -530,6 +535,7 @@ const config = {
'--color-text-primary-inverse': darkThemeRgb.textPrimary,
'--color-text-secondary-inverse': darkThemeRgb.textSecondary,
'--color-text-tertiary-inverse': darkThemeRgb.textTertiary,
'--color-text-hint-inverse': darkThemeRgb.texthint,
'--color-text-disabled-inverse': darkThemeRgb.textDisabled,
'--color-border': lightThemeRgb.border,
@@ -560,6 +566,7 @@ const config = {
'--color-text-primary': darkThemeRgb.textPrimary,
'--color-text-secondary': darkThemeRgb.textSecondary,
'--color-text-tertiary': darkThemeRgb.textTertiary,
'--color-text-hint': darkThemeRgb.textHint,
'--color-text-disabled': darkThemeRgb.textDisabled,
'--color-surface-inverse': lightThemeRgb.surface,
@@ -571,6 +578,7 @@ const config = {
'--color-text-primary-inverse': lightThemeRgb.textPrimary,
'--color-text-secondary-inverse': lightThemeRgb.textSecondary,
'--color-text-tertiary-inverse': lightThemeRgb.textTertiary,
'--color-text-hint-inverse': lightThemeRgb.textHint,
'--color-text-disabled-inverse': lightThemeRgb.textDisabled,
'--color-border': darkThemeRgb.border,
@@ -661,7 +669,7 @@ const config = {
".dark [type='checkbox']:checked": {
backgroundImage: `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")`
},
'input:not(.windmillapp),input[type="text"]:not(.windmillapp),input[type="email"]:not(.windmillapp),input[type="url"]:not(.windmillapp),input[type="password"]:not(.windmillapp),input[type="number"]:not(.windmillapp),input[type="date"]:not(.windmillapp),input[type="datetime-local"]:not(.windmillapp),input[type="month"]:not(.windmillapp),input[type="search"]:not(.windmillapp),input[type="tel"]:not(.windmillapp),input[type="time"]:not(.windmillapp),input[type="week"]:not(.windmillapp),textarea:not(.windmillapp):not(.monaco-mouse-cursor-text),select:not(.windmillapp)':
'input:not(.windmillapp):not(.no-default-style),input[type="text"]:not(.windmillapp):not(.no-default-style),input[type="email"]:not(.windmillapp):not(.no-default-style),input[type="url"]:not(.windmillapp):not(.no-default-style),input[type="password"]:not(.windmillapp):not(.no-default-style),input[type="number"]:not(.windmillapp):not(.no-default-style),input[type="date"]:not(.windmillapp):not(.no-default-style),input[type="datetime-local"]:not(.windmillapp):not(.no-default-style),input[type="month"]:not(.windmillapp):not(.no-default-style),input[type="search"]:not(.windmillapp):not(.no-default-style),input[type="tel"]:not(.windmillapp):not(.no-default-style),input[type="time"]:not(.windmillapp):not(.no-default-style),input[type="week"]:not(.windmillapp):not(.no-default-style),textarea:not(.windmillapp):not(.no-default-style):not(.monaco-mouse-cursor-text),select:not(.windmillapp):not(.no-default-style)':
{
display: 'block',
fontSize: theme('fontSize.sm'),
@@ -686,7 +694,7 @@ const config = {
}
}
},
'.dark input:not(.windmillapp),.dark input[type="text"]:not(.windmillapp),.dark input[type="email"]:not(.windmillapp),.dark input[type="url"]:not(.windmillapp),.dark input[type="password"]:not(.windmillapp),.dark input[type="number"]:not(.windmillapp),.dark input[type="date"]:not(.windmillapp),.dark input[type="datetime-local"]:not(.windmillapp),.dark input[type="month"]:not(.windmillapp),.dark input[type="search"]:not(.windmillapp),.dark input[type="tel"]:not(.windmillapp),.dark input[type="time"]:not(.windmillapp),.dark input[type="week"]:not(.windmillapp),.dark textarea:not(.windmillapp):not(.monaco-mouse-cursor-text),.dark select:not(.windmillapp)':
'.dark input:not(.windmillapp):not(.no-default-style),.dark input[type="text"]:not(.windmillapp):not(.no-default-style),.dark input[type="email"]:not(.windmillapp):not(.no-default-style),.dark input[type="url"]:not(.windmillapp):not(.no-default-style),.dark input[type="password"]:not(.windmillapp):not(.no-default-style),.dark input[type="number"]:not(.windmillapp):not(.no-default-style),.dark input[type="date"]:not(.windmillapp):not(.no-default-style),.dark input[type="datetime-local"]:not(.windmillapp):not(.no-default-style),.dark input[type="month"]:not(.windmillapp):not(.no-default-style),.dark input[type="search"]:not(.windmillapp):not(.no-default-style),.dark input[type="tel"]:not(.windmillapp):not(.no-default-style),.dark input[type="time"]:not(.windmillapp):not(.no-default-style),.dark input[type="week"]:not(.windmillapp):not(.no-default-style),.dark textarea:not(.windmillapp):not(.no-default-style):not(.monaco-mouse-cursor-text),.dark select:not(.windmillapp):not(.no-default-style)':
{
backgroundColor: theme('colors.gray.700'),
color: theme('colors.gray.200'),