Files
windmill/frontend/src/lib/components/JsonEditor.svelte
Ruben Fiszel ebfdb9e514 nits
2025-09-30 12:25:36 +00:00

98 lines
2.3 KiB
Svelte

<script lang="ts">
import '@codingame/monaco-vscode-standalone-json-language-features'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { createEventDispatcher, untrack } 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
value?: any
error?: string
editor?: SimpleEditor | undefined
small?: boolean
loadAsync?: boolean
class?: string | undefined
disabled?: boolean
fixedOverflowWidgets?: boolean
}
let {
code = $bindable(),
value = $bindable(undefined),
error = $bindable(),
editor = $bindable(undefined),
small = false,
loadAsync = false,
class: clazz = undefined,
disabled = false,
fixedOverflowWidgets = true
}: Props = $props()
let tooBig = $derived(code && code?.length > 1000000)
let loadTooBigAnyway = $state(false)
let focused = $state(false)
const dispatch = createEventDispatcher()
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
function parseJson() {
try {
if (code == '') {
value = undefined
error = ''
return
}
value = JSON.parse(code ?? '')
dispatchIfMounted('changeValue', value)
error = ''
} catch (e) {
error = e.message
}
}
$effect(() => {
code != undefined && untrack(() => parseJson())
})
</script>
{#if tooBig && !loadTooBigAnyway}
<div class="flex-1 text-sm">
JSON is too big
<Button size="xs2" variant="border" on:click={() => (loadTooBigAnyway = true)}>
Load anyway
</Button>
</div>
{:else}
<div class="flex flex-col w-full">
<div
class={twMerge(
'w-full rounded-md bg-surface-secondary',
inputBorderClass({ error: !!error, forceFocus: focused })
)}
>
<SimpleEditor
{loadAsync}
{small}
on:focus={() => (dispatch('focus'), (focused = true))}
on:blur={() => (dispatch('blur'), (focused = false))}
bind:this={editor}
on:change
autoHeight
lang="json"
bind:code
class={clazz}
{disabled}
{fixedOverflowWidgets}
renderLineHighlight="none"
yPadding={8}
/>
</div>
{#if error != ''}
<span class="text-red-600 text-xs mt-1">{error}</span>
{/if}
</div>
{/if}