app svelte 5 improvements

This commit is contained in:
Ruben Fiszel
2025-06-29 09:29:28 +00:00
parent b5c561f09e
commit e19c8f47d0
11 changed files with 189 additions and 104 deletions
@@ -164,7 +164,7 @@
{#if data && resolvedConfig.type}
{#key resolvedConfig.type}
{#key options}
<Chart type={resolvedConfig.type} {data} {options} />
<Chart type={resolvedConfig.type} data={$state.snapshot(data)} {options} />
{/key}
{/key}
{/if}
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte'
import { getContext, untrack } from 'svelte'
import { twMerge } from 'tailwind-merge'
import { initConfig, initOutput } from '../../editor/appUtils'
import { components } from '../../editor/component'
@@ -13,17 +13,28 @@
import ResolveStyle from '../helpers/ResolveStyle.svelte'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
export let id: string
export let configuration: RichConfigurations
export let customCss: ComponentCustomCSS<'downloadcomponent'> | undefined = undefined
export let render: boolean
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export let noWFull = false
interface Props {
id: string
configuration: RichConfigurations
customCss?: ComponentCustomCSS<'downloadcomponent'> | undefined
render: boolean
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
noWFull?: boolean
}
const resolvedConfig = initConfig(
components['downloadcomponent'].initialData.configuration,
configuration
let {
id,
configuration,
customCss = undefined,
render,
horizontalAlignment = undefined,
verticalAlignment = undefined,
noWFull = false
}: Props = $props()
const resolvedConfig = $state(
initConfig(components['downloadcomponent'].initialData.configuration, configuration)
)
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
@@ -31,11 +42,8 @@
//used so that we can count number of outputs setup for first refresh
initOutput($worldStore, id, {})
let beforeIconComponent: any
let afterIconComponent: any
$: resolvedConfig.beforeIcon && beforeIconComponent && handleBeforeIcon()
$: resolvedConfig.afterIcon && afterIconComponent && handleAfterIcon()
let beforeIconComponent: any = $state()
let afterIconComponent: any = $state()
async function handleBeforeIcon() {
if (resolvedConfig.beforeIcon) {
@@ -61,7 +69,13 @@
}
}
let css = initCss($app.css?.downloadcomponent, customCss)
let css = $state(initCss($app.css?.downloadcomponent, customCss))
$effect(() => {
resolvedConfig.beforeIcon && beforeIconComponent && untrack(() => handleBeforeIcon())
})
$effect(() => {
resolvedConfig.afterIcon && afterIconComponent && untrack(() => handleAfterIcon())
})
</script>
<InitializeComponent {id} />
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte'
import { getContext, untrack } from 'svelte'
import { initConfig, initOutput } from '../../editor/appUtils'
import {
type AppViewerContext,
@@ -14,19 +14,29 @@
import RecomputeAllWrapper from '../../editor/RecomputeAllWrapper.svelte'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
export let id: string
export let initializing: boolean | undefined = false
export let customCss: ComponentCustomCSS<'jobiddisplaycomponent'> | undefined = undefined
export let configuration: RichConfigurations
export let render: boolean
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
interface Props {
id: string
initializing?: boolean | undefined
customCss?: ComponentCustomCSS<'jobiddisplaycomponent'> | undefined
configuration: RichConfigurations
render: boolean
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
}
let {
id,
initializing = $bindable(false),
customCss = undefined,
configuration,
render,
horizontalAlignment = undefined
}: Props = $props()
const { app, worldStore, policy, recomputeAllContext } =
getContext<AppViewerContext>('AppViewerContext')
let resolvedConfig = initConfig(
components['recomputeallcomponent'].initialData.configuration,
configuration
let resolvedConfig = $state(
initConfig(components['recomputeallcomponent'].initialData.configuration, configuration)
)
initOutput($worldStore, id, {
@@ -35,9 +45,7 @@
initializing = false
let css = initCss($app.css?.recomputeallcomponent, customCss)
$: resolvedConfig.defaultRefreshInterval && handleRefreshInterval()
let css = $state(initCss($app.css?.recomputeallcomponent, customCss))
function handleRefreshInterval() {
if (resolvedConfig.defaultRefreshInterval !== undefined) {
@@ -51,6 +59,9 @@
}
}
}
$effect(() => {
resolvedConfig.defaultRefreshInterval && untrack(() => handleRefreshInterval())
})
</script>
{#each Object.keys(components['recomputeallcomponent'].initialData.configuration) as key (key)}
@@ -158,7 +158,10 @@
if (!resolvedDatasetsValues) {
return
}
const type = resolvedDatasetsValues[index].type
const type = resolvedDatasetsValues?.[index]?.type
if (!type) {
return
}
if (type === 'range-bar' || type === 'range-area') {
return {
type: type,
@@ -361,7 +364,7 @@
bind:darkMode
on:change={(e) => {
tick().then(() => {
updateChart()
chartInstance && resolvedDatasetsValues && updateChart()
})
}}
/>
@@ -9,7 +9,11 @@
import { sendUserToast } from '$lib/toast'
import { getDeleteInput } from './queries/delete'
export let id: string
interface Props {
id: string
}
let { id }: Props = $props()
const { worldStore } = getContext<AppViewerContext>('AppViewerContext')
@@ -19,10 +23,10 @@
jobId: undefined
})
let runnableComponent: RunnableComponent
let loading = false
let runnableComponent: RunnableComponent | undefined = $state()
let loading = $state(false)
let input: AppInput | undefined = undefined
let input: AppInput | undefined = $state(undefined)
const dispatch = createEventDispatcher()
@@ -9,7 +9,11 @@
import { sendUserToast } from '$lib/toast'
import { getInsertInput } from './queries/insert'
export let id: string
interface Props {
id: string
}
let { id }: Props = $props()
const { worldStore } = getContext<AppViewerContext>('AppViewerContext')
@@ -19,9 +23,9 @@
jobId: undefined
})
let runnableComponent: RunnableComponent
let loading = false
let input: AppInput | undefined = undefined
let runnableComponent: RunnableComponent | undefined = $state()
let loading = $state(false)
let input: AppInput | undefined = $state(undefined)
const dispatch = createEventDispatcher()
@@ -1,6 +1,6 @@
<script lang="ts">
import Toggle from '$lib/components/Toggle.svelte'
import { getContext, onDestroy } from 'svelte'
import { getContext, onDestroy, untrack } from 'svelte'
import { initConfig, initOutput } from '../../editor/appUtils'
import type {
AppViewerContext,
@@ -17,20 +17,35 @@
import { twMerge } from 'tailwind-merge'
import ResolveStyle from '../helpers/ResolveStyle.svelte'
export let id: string
export let configuration: RichConfigurations
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export let recomputeIds: string[] | undefined = undefined
export let customCss: ComponentCustomCSS<'checkboxcomponent'> | undefined = undefined
export let render: boolean
export let extraKey: string | undefined = undefined
export let preclickAction: (() => Promise<void>) | undefined = undefined
export let noInitialize = false
export let onToggle: string[] | undefined = undefined
interface Props {
id: string
configuration: RichConfigurations
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
recomputeIds?: string[] | undefined
customCss?: ComponentCustomCSS<'checkboxcomponent'> | undefined
render: boolean
extraKey?: string | undefined
preclickAction?: (() => Promise<void>) | undefined
noInitialize?: boolean
onToggle?: string[] | undefined
controls?: { left: () => boolean; right: () => boolean | string } | undefined
}
export let controls: { left: () => boolean; right: () => boolean | string } | undefined =
undefined
let {
id,
configuration,
horizontalAlignment = undefined,
verticalAlignment = undefined,
recomputeIds = undefined,
customCss = undefined,
render,
extraKey = undefined,
preclickAction = undefined,
noInitialize = false,
onToggle = undefined,
controls = undefined
}: Props = $props()
const { app, worldStore, componentControl, runnableComponents } =
getContext<AppViewerContext>('AppViewerContext')
@@ -39,12 +54,11 @@
const rowContext = getContext<ListContext>('RowWrapperContext')
const rowInputs: ListInputs | undefined = getContext<ListInputs>('RowInputs')
let resolvedConfig = initConfig(
components['checkboxcomponent'].initialData.configuration,
configuration
let resolvedConfig = $state(
initConfig(components['checkboxcomponent'].initialData.configuration, configuration)
)
let value: boolean = resolvedConfig.defaultValue ?? false
let value: boolean = $state(resolvedConfig.defaultValue ?? false)
$componentControl[id] = {
setValue(nvalue: boolean) {
@@ -89,11 +103,15 @@
rowInputs?.remove(id)
})
$: value != undefined && handleInput()
$effect(() => {
value != undefined && untrack(() => handleInput())
})
$: resolvedConfig.defaultValue != undefined && handleDefault()
$effect(() => {
resolvedConfig.defaultValue != undefined && untrack(() => handleDefault())
})
let css = initCss($app.css?.checkboxcomponent, customCss)
let css = $state(initCss($app.css?.checkboxcomponent, customCss))
</script>
{#each Object.keys(components['checkboxcomponent'].initialData.configuration) as key (key)}
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte'
import { getContext, untrack } from 'svelte'
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
@@ -12,27 +12,35 @@
import { initCss } from '../../utils'
import ResolveStyle from '../helpers/ResolveStyle.svelte'
export let id: string
export let configuration: RichConfigurations
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export let render: boolean
export let customCss: ComponentCustomCSS<'selectstepcomponent'> | undefined = undefined
interface Props {
id: string
configuration: RichConfigurations
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
render: boolean
customCss?: ComponentCustomCSS<'selectstepcomponent'> | undefined
}
let {
id,
configuration,
horizontalAlignment = undefined,
verticalAlignment = undefined,
render,
customCss = undefined
}: Props = $props()
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
const resolvedConfig = initConfig(
components['selectstepcomponent'].initialData.configuration,
configuration
const resolvedConfig = $state(
initConfig(components['selectstepcomponent'].initialData.configuration, configuration)
)
const outputs = initOutput($worldStore, id, {
result: undefined as string | undefined
})
let selected: string = ''
let selectedIndex: number = 0
$: resolvedConfig.defaultValue != undefined && setDefaultValue()
let selected: string = $state('')
let selectedIndex: number = $state(0)
$componentControl[id] = {
setValue(nvalue: string) {
@@ -80,8 +88,13 @@
return typeof item == 'string' ? item : item.label
}
let css = initCss($app.css?.selectstepcomponent, customCss)
$: selected && handleSelection(selected)
let css = $state(initCss($app.css?.selectstepcomponent, customCss))
$effect(() => {
resolvedConfig.defaultValue != undefined && untrack(() => setDefaultValue())
})
$effect(() => {
selected && untrack(() => handleSelection(selected))
})
</script>
{#each Object.keys(components['selectstepcomponent'].initialData.configuration) as key (key)}
@@ -112,7 +125,7 @@
class={twMerge(css?.container?.class, 'wm-select-step')}
style={css?.container?.style}
>
<div class="w-full" on:pointerdown={onPointerDown}>
<div class="w-full" onpointerdown={onPointerDown}>
<Stepper
tabs={(resolvedConfig?.items ?? []).map((item) => getLabel(item))}
hasValidations={false}
@@ -17,17 +17,26 @@
import { twMerge } from 'tailwind-merge'
import LightweightResourcePicker from '$lib/components/LightweightResourcePicker.svelte'
export let id: string
export let configuration: RichConfigurations
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export let customCss: ComponentCustomCSS<'userresourcecomponent'> | undefined = undefined
export let render: boolean
interface Props {
id: string
configuration: RichConfigurations
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
customCss?: ComponentCustomCSS<'userresourcecomponent'> | undefined
render: boolean
}
let {
id,
configuration,
verticalAlignment = undefined,
customCss = undefined,
render
}: Props = $props()
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
let resolvedConfig = initConfig(
components['userresourcecomponent'].initialData.configuration,
configuration
let resolvedConfig = $state(
initConfig(components['userresourcecomponent'].initialData.configuration, configuration)
)
const iterContext = getContext<ListContext>('ListWrapperContext')
@@ -37,16 +46,18 @@
result: undefined as string | undefined
})
let css = initCss($app.css?.['userresourcecomponent'], customCss)
let css = $state(initCss($app.css?.['userresourcecomponent'], customCss))
$: classInput = twMerge(
'windmillapp w-full px-2',
css?.input?.class ?? '',
'wm-input',
'wm-user-resource-select'
let classInput = $derived(
twMerge(
'windmillapp w-full px-2',
css?.input?.class ?? '',
'wm-input',
'wm-user-resource-select'
)
)
let value: string | undefined = outputs.result.peak()?.replace('$res:', '')
let value: string | undefined = $state(outputs.result.peak()?.replace('$res:', ''))
value && assignValue(outputs.result.peak())
@@ -76,7 +87,7 @@
}
}
let resourcePicker: LightweightResourcePicker | undefined = undefined
let resourcePicker: LightweightResourcePicker | undefined = $state(undefined)
</script>
{#each Object.keys(components['userresourcecomponent'].initialData.configuration) as key (key)}
@@ -1,6 +1,4 @@
<script lang="ts">
import { run } from 'svelte/legacy'
import { getContext } from 'svelte'
import SubGridEditor from '../../editor/SubGridEditor.svelte'
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
@@ -41,7 +39,7 @@
}: Props = $props()
let everRender = $state(render)
run(() => {
$effect(() => {
render && !everRender && (everRender = true)
})
@@ -62,12 +62,21 @@
/>
{/if}
{#if (`recomputeIds` in item.data && Array.isArray(item.data.recomputeIds)) || item.data.type === 'buttoncomponent' || item.data.type === 'formbuttoncomponent'}
<EventHandlerItem
title="on success"
tooltip="Select components to recompute after this runnable has successfully run"
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
bind:value={item.data.recomputeIds}
/>
{#if item.data.type == 'checkboxcomponent'}
<EventHandlerItem
title="on change"
tooltip="When the value change, regardless of the source"
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
bind:value={item.data.recomputeIds}
/>
{:else}
<EventHandlerItem
title="on success"
tooltip="Select components to recompute after this runnable has successfully run"
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
bind:value={item.data.recomputeIds}
/>
{/if}
{/if}
{#if item.data.type === 'checkboxcomponent'}
<EventHandlerItem