From f0f720f4901aa451f6ecb40c6cf175f5a8148306 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sun, 15 Jun 2025 23:25:34 +0200 Subject: [PATCH] partial app svelte 5 migration (#5945) --- .../components/buttons/AppSchemaForm.svelte | 1 + .../display/AppAccordionList.svelte | 60 ++++-- .../components/display/AppCarouselList.svelte | 129 +++++++----- .../components/helpers/AlignWrapper.svelte | 47 +++-- .../components/inputs/AppMultiSelect.svelte | 191 +---------------- .../layout/AppConditionalWrapper.svelte | 41 ++-- .../components/layout/AppContainer.svelte | 37 +++- .../components/layout/AppDecisionTree.svelte | 90 ++++---- .../apps/components/layout/AppDrawer.svelte | 134 +++++++----- .../apps/components/layout/AppList.svelte | 84 +++++--- .../apps/components/layout/AppModal.svelte | 199 ++++++++++-------- .../components/layout/AppSplitpanes.svelte | 49 +++-- .../components/apps/editor/AppEditor.svelte | 1 + .../apps/editor/SubGridEditor.svelte | 187 ++++++++-------- .../lib/components/apps/editor/appUtils.ts | 2 +- .../components/apps/svelte-grid/Grid.svelte | 142 ++++++++----- .../apps/svelte-grid/MoveResize.svelte | 142 ++++++++----- .../components/apps/svelte-grid/utils/item.ts | 6 +- .../components/details/createAppFromScript.ts | 8 +- .../src/lib/components/tutorials/utils.ts | 3 - .../(root)/(logged)/apps/add/+page.svelte | 29 ++- .../(logged)/apps/edit/[...path]/+page.svelte | 44 ++-- 22 files changed, 849 insertions(+), 777 deletions(-) diff --git a/frontend/src/lib/components/apps/components/buttons/AppSchemaForm.svelte b/frontend/src/lib/components/apps/components/buttons/AppSchemaForm.svelte index e1150f6495..b5e149c134 100644 --- a/frontend/src/lib/components/apps/components/buttons/AppSchemaForm.svelte +++ b/frontend/src/lib/components/apps/components/buttons/AppSchemaForm.svelte @@ -66,6 +66,7 @@ let args: Record = $state(!iterContext ? (outputs?.values?.peak() ?? {}) : {}) function handleArgsChange() { + // console.log('handleArgsChange', args) const newArgs: Record = {} for (const key in args) { diff --git a/frontend/src/lib/components/apps/components/display/AppAccordionList.svelte b/frontend/src/lib/components/apps/components/display/AppAccordionList.svelte index e322e9e783..5155aeb051 100644 --- a/frontend/src/lib/components/apps/components/display/AppAccordionList.svelte +++ b/frontend/src/lib/components/apps/components/display/AppAccordionList.svelte @@ -1,4 +1,7 @@ {#each Object.keys(components['carousellistcomponent'].initialData.configuration) as key (key)} @@ -116,41 +131,45 @@ } }} > -
-
- + if (currentPageIndex > 0) { + carousel.goTo(currentPageIndex - 1) + } else { + carousel.goTo(pagesCount - 1) + } + }} + > + + +
- -
-
- + {/snippet} + {#snippet next()} +
+
+ +
-
+ {/snippet} {#each result ?? [] as value, index}
{#if render}
- + {@render children?.()}
{/if} diff --git a/frontend/src/lib/components/apps/components/inputs/AppMultiSelect.svelte b/frontend/src/lib/components/apps/components/inputs/AppMultiSelect.svelte index 24b02c41c7..d586fd85f3 100644 --- a/frontend/src/lib/components/apps/components/inputs/AppMultiSelect.svelte +++ b/frontend/src/lib/components/apps/components/inputs/AppMultiSelect.svelte @@ -1,206 +1,23 @@ -{#each Object.keys(components['multiselectcomponent'].initialData.configuration) as key (key)} - -{/each} - -{#each Object.keys(css ?? {}) as key (key)} - -{/each} -
{ - $selectedComponent = [id] - - if (!e.shiftKey) { - e.stopPropagation() - } - selectedComponent.set([id]) - }} - use:floatingRef - bind:clientWidth={w} + >This version of the multiselect component is not supported anymore. Recreate the multiselect + component to use this new version.
- {#if !value || Array.isArray(value)} - { - if (event?.type === 'removeAll') { - outputs?.result.set([]) - } else { - outputs?.result.set([...(value ?? [])]) - } - }} - onopen={() => { - $selectedComponent = [id] - open = true - }} - onclose={() => { - open = false - }} - > - {#snippet children({ option })} - - -
{ - let newe = new MouseEvent('mouseup') - e.target?.['parentElement']?.dispatchEvent(newe) - }} - > - {option} -
- {/snippet} -
- - - - {:else} - Value {value} is not an array - {/if} -
diff --git a/frontend/src/lib/components/apps/components/layout/AppConditionalWrapper.svelte b/frontend/src/lib/components/apps/components/layout/AppConditionalWrapper.svelte index 915a1963b6..d3618b6bed 100644 --- a/frontend/src/lib/components/apps/components/layout/AppConditionalWrapper.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppConditionalWrapper.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte b/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte index f9637204fc..c29bb46825 100644 --- a/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte @@ -1,5 +1,5 @@ {#if Object.keys(resolvedConditions).length === nodes.length} diff --git a/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte b/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte index a449a1b532..679bb928c8 100644 --- a/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte @@ -1,4 +1,6 @@ {#each Object.keys(components['drawercomponent'].initialData.configuration) as key (key)} @@ -105,7 +122,7 @@ parentComponentId: id, subGridIndex: 0 } - appDrawer.toggleDrawer() + appDrawer?.toggleDrawer() }} size={resolvedConfig.size} color={resolvedConfig.color} @@ -122,7 +139,6 @@ {#if everRender} - { - appDrawer?.toggleDrawer() - $focusedGrid = undefined - }} - fullScreen={$mode !== 'dnd'} - > -
{ - e?.stopPropagation() - if (!$connectingInput.opened) { - $selectedComponent = [id] - $focusedGrid = { - parentComponentId: id, - subGridIndex: 0 - } - } + {#snippet children({ open })} + { + appDrawer?.toggleDrawer() + $focusedGrid = undefined }} + fullScreen={$mode !== 'dnd'} > - {#if $app.subgrids?.[`${id}-0`]} - { - if (!$connectingInput.opened) { - $selectedComponent = [id] - $focusedGrid = { - parentComponentId: id, - subGridIndex: 0 - } +
{ + e?.stopPropagation() + if (!$connectingInput.opened) { + $selectedComponent = [id] + $focusedGrid = { + parentComponentId: id, + subGridIndex: 0 } - }} - /> - {/if} -
-
+ } + }} + > + {#if $app.subgrids?.[`${id}-0`]} + { + if (!$connectingInput.opened) { + $selectedComponent = [id] + $focusedGrid = { + parentComponentId: id, + subGridIndex: 0 + } + } + }} + /> + {/if} +
+
+ {/snippet}
{:else if $app.subgrids?.[`${id}-0`]} diff --git a/frontend/src/lib/components/apps/components/layout/AppList.svelte b/frontend/src/lib/components/apps/components/layout/AppList.svelte index 6498410036..ef2b906178 100644 --- a/frontend/src/lib/components/apps/components/layout/AppList.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppList.svelte @@ -15,19 +15,32 @@ import { twMerge } from 'tailwind-merge' import ResolveStyle from '../helpers/ResolveStyle.svelte' - export let id: string - export let componentInput: AppInput | undefined - export let configuration: RichConfigurations - export let customCss: ComponentCustomCSS<'listcomponent'> | undefined = undefined - export let render: boolean - export let initializing: boolean | undefined + interface Props { + id: string + componentInput: AppInput | undefined + configuration: RichConfigurations + customCss?: ComponentCustomCSS<'listcomponent'> | undefined + render: boolean + initializing: boolean | undefined + } + + let { + id, + componentInput, + configuration, + customCss = undefined, + render, + initializing = $bindable() + }: Props = $props() const { app, focusedGrid, selectedComponent, worldStore, connectingInput, allIdsInPath, mode } = getContext('AppViewerContext') - let page = 0 + let page = $state(0) - let everRender = render - $: render && !everRender && (everRender = true) + let everRender = $state(render) + $effect.pre(() => { + render && !everRender && (everRender = true) + }) const outputs = initOutput($worldStore, id, { result: undefined, @@ -36,9 +49,8 @@ page: 0 }) - let resolvedConfig = initConfig( - components['listcomponent'].initialData.configuration, - configuration + let resolvedConfig = $state( + initConfig(components['listcomponent'].initialData.configuration, configuration) ) function onFocus() { @@ -48,20 +60,22 @@ } } - let css = initCss($app.css?.listcomponent, customCss) - let result: any[] | undefined = undefined + let css = $state(initCss($app.css?.listcomponent, customCss)) + let result: any[] | undefined = $state(undefined) - $: isCard = resolvedConfig.width?.selected == 'card' + let isCard = $derived(resolvedConfig.width?.selected == 'card') - let inputs = {} - let loading: boolean = false - let isPreviousLoading = false - let isNextLoading = false + let inputs = $state({}) + let loading: boolean = $state(false) + let isPreviousLoading = $state(false) + let isNextLoading = $state(false) - $: if (!loading) { - isPreviousLoading = false - isNextLoading = false - } + $effect.pre(() => { + if (!loading) { + isPreviousLoading = false + isNextLoading = false + } + }) function getPagination( configuration: { @@ -99,11 +113,13 @@ } } - $: pagination = getPagination( - resolvedConfig.pagination?.configuration, - resolvedConfig.pagination?.selected, - result, - page + let pagination = $derived( + getPagination( + resolvedConfig.pagination?.configuration, + resolvedConfig.pagination?.selected, + result, + page + ) ) @@ -150,8 +166,8 @@ : 'overflow-auto'} {isCard ? 'gap-2 flex-wrap' : resolvedConfig?.displayBorders - ? 'divide-y flex-col' - : 'flex-col'}" + ? 'divide-y flex-col' + : 'flex-col'}" > {#if $app.subgrids?.[`${id}-0`] && Array.isArray(result) && result.length > 0} {#each result ?? [] as value, index (index)} @@ -162,16 +178,16 @@ isCard ? `min-width: ${resolvedConfig.width?.configuration?.card?.minWidthPx}px; ` : '' - } max-height: ${resolvedConfig.heightPx}px;` + } max-height: ${resolvedConfig.heightPx}px;` : ''} class={inRange ? `${ $allIdsInPath.includes(id) ? 'overflow-visible' : resolvedConfig.heightPx - ? 'overflow-auto' - : '' - } ${!isCard ? 'w-full' : resolvedConfig?.displayBorders ? 'border' : ''}` + ? 'overflow-auto' + : '' + } ${!isCard ? 'w-full' : resolvedConfig?.displayBorders ? 'border' : ''}` : 'h-0 float overflow-hidden invisible absolute'} > + import { stopPropagation } from 'svelte/legacy' + import { getContext } from 'svelte' import SubGridEditor from '../../editor/SubGridEditor.svelte' import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types' @@ -17,16 +19,29 @@ import Disposable from '$lib/components/common/drawer/Disposable.svelte' import AlignWrapper from '../helpers/AlignWrapper.svelte' - export let customCss: ComponentCustomCSS<'modalcomponent'> | undefined = undefined - 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 noWFull = false - export let render: boolean + interface Props { + customCss?: ComponentCustomCSS<'modalcomponent'> | undefined + id: string + configuration: RichConfigurations + horizontalAlignment?: 'left' | 'center' | 'right' | undefined + verticalAlignment?: 'top' | 'center' | 'bottom' | undefined + noWFull?: boolean + render: boolean + onOpenRecomputeIds?: string[] | undefined + onCloseRecomputeIds?: string[] | undefined + } - export let onOpenRecomputeIds: string[] | undefined = undefined - export let onCloseRecomputeIds: string[] | undefined = undefined + let { + customCss = undefined, + id, + configuration, + horizontalAlignment = undefined, + verticalAlignment = undefined, + noWFull = false, + render, + onOpenRecomputeIds = undefined, + onCloseRecomputeIds = undefined + }: Props = $props() const { app, @@ -40,23 +55,24 @@ breakpoint } = getContext('AppViewerContext') - let everRender = render - $: render && !everRender && (everRender = true) + let everRender = $state(render) + $effect.pre(() => { + render && !everRender && (everRender = true) + }) //used so that we can count number of outputs setup for first refresh const outputs = initOutput($worldStore, id, { open: false }) - let css = initCss($app.css?.modalcomponent, customCss) - let disposable: Disposable | undefined = undefined + let css = $state(initCss($app.css?.modalcomponent, customCss)) + let disposable: Disposable | undefined = $state(undefined) - let resolvedConfig = initConfig( - components['modalcomponent'].initialData.configuration, - configuration + let resolvedConfig = $state( + initConfig(components['modalcomponent'].initialData.configuration, configuration) ) - let unclickableOutside = false + let unclickableOutside = $state(false) function unclosableModal() { unclickableOutside = true setTimeout(() => { @@ -81,14 +97,16 @@ disposable?.closeDrawer() } } - let wrapperHeight: number = 0 - let headerHeight: number = 0 + let wrapperHeight: number = $state(0) + let headerHeight: number = $state(0) - $: containerHeight = Math.min( - // 8px * 2 of padding - maxHeight($app.subgrids?.[`${id}-0`] ?? [], 0, $breakpoint) * (ROW_HEIGHT + ROW_GAP_Y) + 16, - // 32px (2rem) of top and bottom margin - wrapperHeight - headerHeight - 64 + let containerHeight = $derived( + Math.min( + // 8px * 2 of padding + maxHeight($app.subgrids?.[`${id}-0`] ?? [], 0, $breakpoint) * (ROW_HEIGHT + ROW_GAP_Y) + 16, + // 32px (2rem) of top and bottom margin + wrapperHeight - headerHeight - 64 + ) ) async function getMenuElements(): Promise { @@ -154,9 +172,6 @@ { outputs?.open.set(true) @@ -167,80 +182,82 @@ onCloseRecomputeIds?.forEach((id) => $runnableComponents?.[id]?.cb?.map((cb) => cb?.())) }} > -
+ {#snippet children({ handleClickAway, zIndex, open })}
{ - if ($mode !== 'dnd' && !unclickableOutside) { - handleClickAway(e) - } - }} + class={twMerge( + `${ + $mode == 'dnd' ? 'absolute' : 'fixed' + } top-0 bottom-0 left-0 right-0 transition-all duration-50`, + open ? ' bg-black bg-opacity-60' : 'h-0 overflow-hidden invisible' + )} + style="z-index: {zIndex}" + bind:clientHeight={wrapperHeight} >
-
{resolvedConfig.modalTitle}
-
- -
-
- -
{ - e?.stopPropagation() - if (!$connectingInput.opened) { - $selectedComponent = [id] - $focusedGrid = { - parentComponentId: id, - subGridIndex: 0 + style={css?.popup?.style} + class={twMerge('mx-24 mt-8 bg-surface wm-modal rounded-lg relative', css?.popup?.class)} + use:clickOutside={{ + capture: false, + stopPropagation: false, + exclude: getMenuElements, + onClickOutside: (e: MouseEvent) => { + if ($mode !== 'dnd' && !unclickableOutside) { + handleClickAway(e) } } }} > - {#if $app.subgrids?.[`${id}-0`]} - { - if (!$connectingInput.opened) { - $selectedComponent = [id] - $focusedGrid = { - parentComponentId: id, - subGridIndex: 0 - } +
+
{resolvedConfig.modalTitle}
+
+ +
+
+ +
{ + e?.stopPropagation() + if (!$connectingInput.opened) { + $selectedComponent = [id] + $focusedGrid = { + parentComponentId: id, + subGridIndex: 0 } - }} - /> - {/if} + } + }} + > + {#if $app.subgrids?.[`${id}-0`]} + { + if (!$connectingInput.opened) { + $selectedComponent = [id] + $focusedGrid = { + parentComponentId: id, + subGridIndex: 0 + } + } + }} + /> + {/if} +
-
+ {/snippet}
{:else if $app.subgrids?.[`${id}-0`]} diff --git a/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte b/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte index 90dbf14618..4424280ced 100644 --- a/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte @@ -1,4 +1,6 @@ {#each Object.keys(css ?? {}) as key (key)} @@ -87,20 +102,20 @@ {#if everRender} -
+
{#key sumedup} {#each sumedup as paneSize, index (index)}
{ + onpointerdown={stopPropagation(() => { $selectedComponent = [id] $focusedGrid = { parentComponentId: id, subGridIndex: index } - }} + })} > {#if $app.subgrids?.[`${id}-${index}`]} + import { stopPropagation } from 'svelte/legacy' + import { push } from '$lib/history' import { classNames } from '$lib/utils' import { createEventDispatcher, getContext, onDestroy } from 'svelte' @@ -21,18 +23,31 @@ import GridViewer from './GridViewer.svelte' import GridEditorMenu from './GridEditorMenu.svelte' - export let containerHeight: number | undefined = undefined - export let containerWidth: number | undefined = undefined - let classes = '' + interface Props { + containerHeight?: number | undefined + containerWidth?: number | undefined + class?: string + style?: string + noPadding?: boolean + noYPadding?: boolean + subGridId: string + visible?: boolean + id: string + shouldHighlight?: boolean + } - export { classes as class } - export let style = '' - export let noPadding = false - export let noYPadding = false - export let subGridId: string - export let visible: boolean = true - export let id: string - export let shouldHighlight: boolean = true + let { + containerHeight = undefined, + containerWidth = undefined, + class: classes = '', + style = '', + noPadding = false, + noYPadding = false, + subGridId, + visible = true, + id, + shouldHighlight = true + }: Props = $props() const dispatch = createEventDispatcher() @@ -50,17 +65,19 @@ const editorContext = getContext('AppEditorContext') - let isActive = false + let isActive = $state(false) let sber = editorContext?.componentActive?.subscribe((x) => (isActive = x)) - let everVisible = visible + let everVisible = $state(visible) - $: visible && !everVisible && (everVisible = true) + $effect.pre(() => { + visible && !everVisible && (everVisible = true) + }) onDestroy(() => { sber?.() }) - $: highlight = id === $focusedGrid?.parentComponentId && shouldHighlight + let highlight = $derived(id === $focusedGrid?.parentComponentId && shouldHighlight) const onpointerdown = (e) => { dispatch('focus') @@ -80,9 +97,11 @@ $app = $app } - let container: HTMLElement | undefined = undefined + let container: HTMLElement | undefined = $state(undefined) - $: maxRow = maxHeight($app.subgrids?.[subGridId] ?? [], containerHeight ?? 0, $breakpoint) + let maxRow = $derived( + maxHeight($app.subgrids?.[subGridId] ?? [], containerHeight ?? 0, $breakpoint) + ) export function moveComponentBetweenSubgrids( componentId: string, @@ -177,13 +196,15 @@ } + {#if everVisible || $app.eagerRendering} diff --git a/frontend/src/lib/components/apps/editor/appUtils.ts b/frontend/src/lib/components/apps/editor/appUtils.ts index 77ddb84f27..fe0fc8e47b 100644 --- a/frontend/src/lib/components/apps/editor/appUtils.ts +++ b/frontend/src/lib/components/apps/editor/appUtils.ts @@ -476,7 +476,7 @@ export function appComponentFromType( ), recomputeIds: init.recomputeIds ? [] : undefined, actionButtons: init.actionButtons ? [] : undefined, - actions: [], + actions: undefined, menuItems: init.menuItems ? [] : undefined, numberOfSubgrids: init.numberOfSubgrids, horizontalAlignment: override?.horizontalAlignment ?? init.horizontalAlignment, diff --git a/frontend/src/lib/components/apps/svelte-grid/Grid.svelte b/frontend/src/lib/components/apps/svelte-grid/Grid.svelte index 889ee75a39..8c3047806c 100644 --- a/frontend/src/lib/components/apps/svelte-grid/Grid.svelte +++ b/frontend/src/lib/components/apps/svelte-grid/Grid.svelte @@ -1,4 +1,4 @@ - { + onfocus={() => { if ($isCtrlOrMetaPressedStore) { $isCtrlOrMetaPressedStore = false } }} - on:keydown={handleKeyDown} - on:keyup={handleKeyUp} + onkeydown={handleKeyDown} + onkeyup={handleKeyUp} />
handleInitMove(item.id)} - on:move={handleMove} + onMove={handleMove} bind:shadow={shadows[item.id]} bind:this={moveResizes[item.id]} on:repaint={handleRepaint} @@ -502,13 +538,13 @@ {disableMove} > {#if item[getComputedCols]} -