mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-26 00:03:59 +00:00
iterate
This commit is contained in:
@@ -3,10 +3,15 @@
|
||||
import type { Writable } from 'svelte/store'
|
||||
import type { GroupContext } from '../types'
|
||||
|
||||
export let context: Writable<Record<string, any>>
|
||||
export let id: string
|
||||
interface Props {
|
||||
context: Writable<Record<string, any>>
|
||||
id: string
|
||||
children?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
let { context, id, children }: Props = $props()
|
||||
|
||||
setContext<GroupContext>('GroupContext', { id, context })
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
let errors: Record<string, string> = {}
|
||||
|
||||
let css = $state(initCss($app?.css?.formbuttoncomponent, customCss))
|
||||
let css = $state(initCss(app?.css?.formbuttoncomponent, customCss))
|
||||
let runnableWrapper: RunnableWrapper | undefined = $state()
|
||||
let loading = $state(false)
|
||||
let modal: AlwaysMountedModal | undefined = $state()
|
||||
@@ -93,7 +93,7 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.formbuttoncomponent}
|
||||
componentStyle={app.css?.formbuttoncomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let css = $state(initCss($app.css?.schemaformcomponent, customCss))
|
||||
let css = $state(initCss(app.css?.schemaformcomponent, customCss))
|
||||
|
||||
const resolvedConfig = $state(
|
||||
initConfig(components['schemaformcomponent'].initialData.configuration, configuration)
|
||||
@@ -125,7 +125,15 @@
|
||||
return policy
|
||||
}
|
||||
$effect(() => {
|
||||
args && untrack(() => handleArgsChange())
|
||||
if (!args) return
|
||||
{
|
||||
if (args && typeof args === 'object') {
|
||||
for (const key in args) {
|
||||
args[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
untrack(() => handleArgsChange())
|
||||
})
|
||||
$effect(() => {
|
||||
outputs.valid.set(valid)
|
||||
@@ -152,7 +160,7 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.schemaformcomponent}
|
||||
componentStyle={app.css?.schemaformcomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
@@ -164,8 +172,7 @@
|
||||
>
|
||||
<div
|
||||
onpointerdown={stopPropagation(
|
||||
(e) =>
|
||||
!$connectingInput.opened && selectId(e as PointerEvent, id, selectedComponent, $app)
|
||||
(e) => !$connectingInput.opened && selectId(e as PointerEvent, id, selectedComponent, app)
|
||||
)}
|
||||
>
|
||||
<SchemaForm
|
||||
|
||||
+31
-20
@@ -18,18 +18,27 @@
|
||||
import DisplayResult from '$lib/components/DisplayResult.svelte'
|
||||
import { userStore } from '$lib/stores'
|
||||
|
||||
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
|
||||
interface Props {
|
||||
id: string
|
||||
initializing?: boolean | undefined
|
||||
customCss?: ComponentCustomCSS<'jobiddisplaycomponent'> | undefined
|
||||
configuration: RichConfigurations
|
||||
render: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
initializing = $bindable(false),
|
||||
customCss = undefined,
|
||||
configuration,
|
||||
render
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, workspace, appPath } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const requireHtmlApproval = getContext<boolean | undefined>(IS_APP_PUBLIC_CONTEXT_KEY)
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['jobiddisplaycomponent'].initialData.configuration,
|
||||
configuration
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['jobiddisplaycomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
@@ -40,18 +49,20 @@
|
||||
|
||||
initializing = false
|
||||
|
||||
let css = initCss($app.css?.jobiddisplaycomponent, customCss)
|
||||
let css = $state(initCss(app.css?.jobiddisplaycomponent, customCss))
|
||||
|
||||
let testJobLoader: TestJobLoader | undefined = undefined
|
||||
let testIsLoading: boolean = false
|
||||
let testJob: Job | undefined = undefined
|
||||
let testJobLoader: TestJobLoader | undefined = $state(undefined)
|
||||
let testIsLoading: boolean = $state(false)
|
||||
let testJob: Job | undefined = $state(undefined)
|
||||
|
||||
$: if (resolvedConfig.jobId) {
|
||||
outputs.loading.set(true)
|
||||
testJobLoader?.watchJob(resolvedConfig?.['jobId'])
|
||||
}
|
||||
$effect(() => {
|
||||
if (resolvedConfig.jobId) {
|
||||
outputs.loading.set(true)
|
||||
testJobLoader?.watchJob(resolvedConfig?.['jobId'])
|
||||
}
|
||||
})
|
||||
|
||||
let result: any = undefined
|
||||
let result: any = $state(undefined)
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['jobiddisplaycomponent'].initialData.configuration) as key (key)}
|
||||
@@ -69,7 +80,7 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.jobiddisplaycomponent}
|
||||
componentStyle={app.css?.jobiddisplaycomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
@@ -101,13 +112,13 @@
|
||||
</div>
|
||||
<div
|
||||
style={twMerge(
|
||||
$app.css?.['displaycomponent']?.['container']?.style,
|
||||
app.css?.['displaycomponent']?.['container']?.style,
|
||||
customCss?.container?.style,
|
||||
'wm-rich-result-container'
|
||||
)}
|
||||
class={twMerge(
|
||||
'p-2 grow overflow-auto',
|
||||
$app.css?.['displaycomponent']?.['container']?.class,
|
||||
app.css?.['displaycomponent']?.['container']?.class,
|
||||
customCss?.container?.class
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
initializing = false
|
||||
|
||||
let css = initCss($app.css?.recomputeallcomponent, customCss)
|
||||
let css = initCss(app.css?.recomputeallcomponent, customCss)
|
||||
|
||||
$: resolvedConfig.defaultRefreshInterval && handleRefreshInterval()
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.recomputeallcomponent}
|
||||
componentStyle={app.css?.recomputeallcomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { run, createBubbler, stopPropagation } from 'svelte/legacy'
|
||||
|
||||
const bubble = createBubbler()
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { Clipboard } from 'lucide-svelte'
|
||||
import { getContext } from 'svelte'
|
||||
@@ -15,23 +18,34 @@
|
||||
import { initCss } from '../../utils'
|
||||
import ResolveStyle from '../helpers/ResolveStyle.svelte'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = 'left'
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let configuration: RichConfigurations
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'textcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
export let editorMode: boolean = false
|
||||
interface Props {
|
||||
id: string
|
||||
componentInput: AppInput | undefined
|
||||
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
|
||||
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
|
||||
configuration: RichConfigurations
|
||||
initializing?: boolean | undefined
|
||||
customCss?: ComponentCustomCSS<'textcomponent'> | undefined
|
||||
render: boolean
|
||||
editorMode?: boolean
|
||||
}
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['textcomponent'].initialData.configuration,
|
||||
configuration
|
||||
let {
|
||||
id,
|
||||
componentInput,
|
||||
horizontalAlignment = 'left',
|
||||
verticalAlignment = undefined,
|
||||
configuration,
|
||||
initializing = $bindable(undefined),
|
||||
customCss = undefined,
|
||||
render,
|
||||
editorMode = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['textcomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
$: editorMode && onEditorMode()
|
||||
|
||||
function onEditorMode() {
|
||||
autosize()
|
||||
setTimeout(() => autosize(), 50)
|
||||
@@ -39,9 +53,9 @@
|
||||
const { app, worldStore, mode, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let css = initCss($app.css?.textcomponent, customCss)
|
||||
let css = $state(initCss(app.css?.textcomponent, customCss))
|
||||
|
||||
let result: string | undefined = undefined
|
||||
let result: string | undefined = $state(undefined)
|
||||
|
||||
if (
|
||||
componentInput?.type == 'template' ||
|
||||
@@ -108,16 +122,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
let component = 'p'
|
||||
let classes = ''
|
||||
|
||||
$: resolvedConfig.style && (component = getComponent())
|
||||
$: resolvedConfig.style && (classes = getClasses())
|
||||
$: initialValue =
|
||||
componentInput?.type == 'template' || componentInput?.type == 'templatev2'
|
||||
? componentInput.eval
|
||||
: ''
|
||||
$: editableValue = initialValue ?? ''
|
||||
let component = $state('p')
|
||||
let classes = $state('')
|
||||
|
||||
let rows = 1
|
||||
|
||||
@@ -140,6 +146,21 @@
|
||||
// console.log(el, el?.scrollHeight)
|
||||
}, 0)
|
||||
}
|
||||
run(() => {
|
||||
editorMode && onEditorMode()
|
||||
})
|
||||
run(() => {
|
||||
resolvedConfig.style && (component = getComponent())
|
||||
})
|
||||
run(() => {
|
||||
resolvedConfig.style && (classes = getClasses())
|
||||
})
|
||||
let initialValue = $derived(
|
||||
componentInput?.type == 'template' || componentInput?.type == 'templatev2'
|
||||
? componentInput.eval
|
||||
: ''
|
||||
)
|
||||
let editableValue = $derived(initialValue ?? '')
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['textcomponent'].initialData.configuration) as key (key)}
|
||||
@@ -157,22 +178,22 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.textcomponent}
|
||||
componentStyle={app.css?.textcomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<RunnableWrapper {outputs} {render} {componentInput} {id} bind:initializing bind:result>
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class={twMerge('h-full w-full overflow-hidden', css.container?.class, 'wm-text-container')}
|
||||
style={css?.container?.style}
|
||||
on:dblclick={() => {
|
||||
ondblclick={() => {
|
||||
if (!editorMode) {
|
||||
editorMode = true
|
||||
document.getElementById(`text-${id}`)?.focus()
|
||||
}
|
||||
}}
|
||||
on:keydown|stopPropagation
|
||||
onkeydown={stopPropagation(bubble('keydown'))}
|
||||
>
|
||||
{#if $mode == 'dnd' && editorMode && (componentInput?.type == 'template' || componentInput?.type == 'templatev2')}
|
||||
<AlignWrapper {verticalAlignment}>
|
||||
@@ -187,20 +208,20 @@
|
||||
horizontalAlignment === 'center'
|
||||
? 'text-center'
|
||||
: horizontalAlignment === 'right'
|
||||
? 'text-right'
|
||||
: 'text-left'
|
||||
? 'text-right'
|
||||
: 'text-left'
|
||||
)}
|
||||
on:pointerdown|stopPropagation
|
||||
onpointerdown={stopPropagation(bubble('pointerdown'))}
|
||||
style={css?.text?.style}
|
||||
id={`text-${id}`}
|
||||
on:pointerenter={() => {
|
||||
onpointerenter={() => {
|
||||
const elem = document.getElementById(`text-${id}`)
|
||||
if (elem) {
|
||||
elem.focus()
|
||||
}
|
||||
}}
|
||||
{rows}
|
||||
on:input={onInput}
|
||||
oninput={onInput}
|
||||
value={editableValue}
|
||||
></textarea>
|
||||
</AlignWrapper>
|
||||
@@ -215,7 +236,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
class="flex flex-wrap gap-0.5 pb-0.5 w-full {$mode === 'dnd' &&
|
||||
(componentInput?.type == 'template' || componentInput?.type == 'templatev2')
|
||||
@@ -232,8 +253,8 @@
|
||||
horizontalAlignment === 'center'
|
||||
? 'text-center'
|
||||
: horizontalAlignment === 'right'
|
||||
? 'text-right'
|
||||
: 'text-left'
|
||||
? 'text-right'
|
||||
: 'text-left'
|
||||
)}
|
||||
style={css?.text?.style}
|
||||
>
|
||||
|
||||
@@ -369,7 +369,7 @@
|
||||
const uuid = await executeRunnable(
|
||||
runnable,
|
||||
workspace,
|
||||
$app.version,
|
||||
app.version,
|
||||
$userStore?.username,
|
||||
$appPath,
|
||||
id,
|
||||
@@ -436,7 +436,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
const oneOfRunnableInputs = isEditor ? collectOneOfFields(fields, $app) : {}
|
||||
const oneOfRunnableInputs = isEditor ? collectOneOfFields(fields, app) : {}
|
||||
|
||||
const requestBody: ExecuteComponentData['requestBody'] = {
|
||||
args: nonStaticRunnableInputs,
|
||||
@@ -608,7 +608,7 @@
|
||||
|
||||
function handleInputClick(e: CustomEvent) {
|
||||
const event = e as unknown as PointerEvent
|
||||
!$connectingInput.opened && selectId(event, id, selectedComponent, $app)
|
||||
!$connectingInput.opened && selectId(event, id, selectedComponent, app)
|
||||
}
|
||||
|
||||
let cancellableRun: ((inlineScript?: InlineScript) => CancelablePromise<void>) | undefined =
|
||||
|
||||
@@ -12,23 +12,37 @@
|
||||
import GroupWrapper from '../GroupWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
|
||||
export let id: string
|
||||
export let componentContainerHeight: number
|
||||
export let customCss: ComponentCustomCSS<'containercomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
export let groupFields: RichConfigurations | undefined = undefined
|
||||
interface Props {
|
||||
id: string
|
||||
componentContainerHeight: number
|
||||
customCss?: ComponentCustomCSS<'containercomponent'> | undefined
|
||||
render: boolean
|
||||
groupFields?: RichConfigurations | undefined
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
componentContainerHeight,
|
||||
customCss = undefined,
|
||||
render,
|
||||
groupFields = undefined
|
||||
}: Props = $props()
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let everRender = render
|
||||
$: render && !everRender && (everRender = true)
|
||||
let everRender = $state(render)
|
||||
$effect(() => {
|
||||
render && !everRender && (everRender = true)
|
||||
})
|
||||
|
||||
let groupContext = writable({})
|
||||
|
||||
let outputs = initOutput($worldStore, id, { group: $groupContext })
|
||||
|
||||
$: outputs.group.set($groupContext, true)
|
||||
$effect(() => {
|
||||
outputs.group.set($groupContext, true)
|
||||
})
|
||||
|
||||
function onFocus() {
|
||||
$focusedGrid = {
|
||||
@@ -48,7 +62,7 @@
|
||||
}
|
||||
})
|
||||
|
||||
let css = initCss($app.css?.containercomponent, customCss)
|
||||
let css = $state(initCss(app.css?.containercomponent, customCss))
|
||||
</script>
|
||||
|
||||
<InitializeComponent {id} />
|
||||
@@ -59,7 +73,7 @@
|
||||
{customCss}
|
||||
{key}
|
||||
bind:css={css[key]}
|
||||
componentStyle={$app.css?.containercomponent}
|
||||
componentStyle={app.css?.containercomponent}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
@@ -71,7 +85,7 @@
|
||||
|
||||
{#if everRender}
|
||||
<div class="w-full h-full">
|
||||
{#if $app.subgrids?.[`${id}-0`]}
|
||||
{#if app.subgrids?.[`${id}-0`]}
|
||||
<GroupWrapper {id} context={groupContext}>
|
||||
<SubGridEditor
|
||||
visible={render}
|
||||
@@ -90,7 +104,7 @@
|
||||
</GroupWrapper>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if $app.subgrids?.[`${id}-0`]}
|
||||
{:else if app.subgrids?.[`${id}-0`]}
|
||||
<GroupWrapper {id} context={groupContext}>
|
||||
<SubGridEditor visible={false} {id} subGridId={`${id}-0`} />
|
||||
</GroupWrapper>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let resourceOnly: boolean = true
|
||||
let resourceOnly: boolean = $state(true)
|
||||
</script>
|
||||
|
||||
<Alert type="info" title="Configurations">
|
||||
@@ -19,7 +19,7 @@
|
||||
<Toggle bind:checked={resourceOnly} options={{ right: 'Resource only' }} />
|
||||
</div>
|
||||
<div class="gap-4 flex flex-col pt-4">
|
||||
{#each allItems($app.grid, $app.subgrids) as gridItem (gridItem.data.id)}
|
||||
{#each allItems(app.grid, app.subgrids) as gridItem (gridItem.data.id)}
|
||||
{#if gridItem?.data?.type === 'tablecomponent'}
|
||||
<div>
|
||||
<AppComponentInput bind:component={gridItem.data} {resourceOnly} />
|
||||
@@ -52,10 +52,10 @@
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if $app?.hiddenInlineScripts?.length > 0}
|
||||
{#if app?.hiddenInlineScripts?.length > 0}
|
||||
<div class="font-bold text-lg">Background runnable inputs</div>
|
||||
<div class="gap-4 flex flex-col pt-4">
|
||||
{#each $app?.hiddenInlineScripts ?? [] as script, index (script.name)}
|
||||
{#each app?.hiddenInlineScripts ?? [] as script, index (script.name)}
|
||||
<div class="border p-2">
|
||||
<div class="text-sm font-bold">{script.name}</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { run } 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>('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)
|
||||
run(() => {
|
||||
visible && !everVisible && (everVisible = true)
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
sber?.()
|
||||
})
|
||||
$: highlight = id === $focusedGrid?.parentComponentId && shouldHighlight
|
||||
let highlight = $derived(id === $focusedGrid?.parentComponentId && shouldHighlight)
|
||||
|
||||
const onpointerdown = (e) => {
|
||||
dispatch('focus')
|
||||
@@ -68,21 +85,23 @@
|
||||
|
||||
function selectComponent(e: PointerEvent, id: string) {
|
||||
if (!$connectingInput.opened) {
|
||||
selectId(e, id, selectedComponent, $app)
|
||||
selectId(e, id, selectedComponent, app)
|
||||
}
|
||||
}
|
||||
|
||||
function lock(dataItem: GridItem) {
|
||||
let fComponent = findGridItem($app, dataItem.id)
|
||||
let fComponent = findGridItem(app, dataItem.id)
|
||||
if (fComponent) {
|
||||
fComponent = toggleFixed(fComponent)
|
||||
}
|
||||
// $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,
|
||||
@@ -91,27 +110,27 @@
|
||||
position?: { x: number; y: number }
|
||||
) {
|
||||
// Find the component in the source subgrid
|
||||
const component = findGridItem($app, componentId)
|
||||
const component = findGridItem(app, componentId)
|
||||
|
||||
if (!component) {
|
||||
return
|
||||
}
|
||||
|
||||
let parentGrid = findGridItemParentGrid($app, component.id)
|
||||
let parentGrid = findGridItemParentGrid(app, component.id)
|
||||
|
||||
if (parentGrid) {
|
||||
$app.subgrids &&
|
||||
($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter(
|
||||
app.subgrids &&
|
||||
(app.subgrids[parentGrid] = app.subgrids[parentGrid].filter(
|
||||
(item) => item.id !== component?.id
|
||||
))
|
||||
} else {
|
||||
$app.grid = $app.grid.filter((item) => item.id !== component?.id)
|
||||
app.grid = app.grid.filter((item) => item.id !== component?.id)
|
||||
}
|
||||
|
||||
const gridItem = component
|
||||
|
||||
insertNewGridItem(
|
||||
$app,
|
||||
app,
|
||||
(id) => ({ ...gridItem.data, id }),
|
||||
{ parentComponentId: parentComponentId, subGridIndex: subGridIndex },
|
||||
Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])),
|
||||
@@ -123,8 +142,8 @@
|
||||
true
|
||||
)
|
||||
|
||||
// Update the app state
|
||||
$app = { ...$app }
|
||||
// // Update the app state
|
||||
// $app = { ...$app }
|
||||
|
||||
if (parentGrid) {
|
||||
$focusedGrid = {
|
||||
@@ -140,27 +159,27 @@
|
||||
|
||||
export function moveToRoot(componentId: string, position?: { x: number; y: number }) {
|
||||
// Find the component in the source subgrid
|
||||
const component = findGridItem($app, componentId)
|
||||
const component = findGridItem(app, componentId)
|
||||
|
||||
if (!component) {
|
||||
return
|
||||
}
|
||||
|
||||
let parentGrid = findGridItemParentGrid($app, component.id)
|
||||
let parentGrid = findGridItemParentGrid(app, component.id)
|
||||
|
||||
if (parentGrid) {
|
||||
$app.subgrids &&
|
||||
($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter(
|
||||
app.subgrids &&
|
||||
(app.subgrids[parentGrid] = app.subgrids[parentGrid].filter(
|
||||
(item) => item.id !== component?.id
|
||||
))
|
||||
} else {
|
||||
$app.grid = $app.grid.filter((item) => item.id !== component?.id)
|
||||
app.grid = app.grid.filter((item) => item.id !== component?.id)
|
||||
}
|
||||
|
||||
const gridItem = component
|
||||
|
||||
insertNewGridItem(
|
||||
$app,
|
||||
app,
|
||||
(id) => ({ ...gridItem.data, id }),
|
||||
undefined,
|
||||
Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])),
|
||||
@@ -173,17 +192,17 @@
|
||||
)
|
||||
|
||||
// Update the app state
|
||||
$app = { ...$app }
|
||||
// $app = { ...$app }
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if everVisible || $app.eagerRendering}
|
||||
{#if everVisible || app.eagerRendering}
|
||||
<div
|
||||
class="translate-x-0 translate-y-0 w-full subgrid {visible
|
||||
? 'visible'
|
||||
: 'invisible h-0 overflow-hidden'}"
|
||||
bind:this={container}
|
||||
on:pointerdown={onpointerdown}
|
||||
{onpointerdown}
|
||||
>
|
||||
<div
|
||||
class={twMerge(
|
||||
@@ -206,18 +225,14 @@
|
||||
>
|
||||
<Grid
|
||||
allIdsInPath={$allIdsInPath}
|
||||
items={$app.subgrids?.[subGridId] ?? []}
|
||||
items={app.subgrids?.[subGridId] ?? []}
|
||||
on:redraw={(e) => {
|
||||
push(editorContext?.history, $app)
|
||||
if ($app.subgrids) {
|
||||
$app.subgrids[subGridId] = e.detail
|
||||
push(editorContext?.history, app)
|
||||
if (app.subgrids) {
|
||||
app.subgrids[subGridId] = e.detail
|
||||
}
|
||||
}}
|
||||
selectedIds={$selectedComponent}
|
||||
let:dataItem
|
||||
let:overlapped
|
||||
let:moveMode
|
||||
let:componentDraggedId
|
||||
scroller={container}
|
||||
parentWidth={$parentWidth - 17}
|
||||
{containerWidth}
|
||||
@@ -227,7 +242,7 @@
|
||||
if (!overlapped) {
|
||||
moveToRoot(id, { x, y })
|
||||
} else {
|
||||
const overlappedComponent = findGridItem($app, overlapped)
|
||||
const overlappedComponent = findGridItem(app, overlapped)
|
||||
|
||||
if (overlappedComponent && !isContainer(overlappedComponent.data.type)) {
|
||||
return
|
||||
@@ -250,87 +265,93 @@
|
||||
}}
|
||||
disableMove={!!$connectingInput.opened}
|
||||
>
|
||||
<ComponentWrapper
|
||||
id={dataItem.id}
|
||||
type={dataItem.data.type}
|
||||
class={classNames(
|
||||
'h-full w-full center-center',
|
||||
$selectedComponent?.includes(dataItem.id) ? 'active-grid-item' : '',
|
||||
'top-0'
|
||||
)}
|
||||
>
|
||||
<GridEditorMenu id={dataItem.id}>
|
||||
<Component
|
||||
{overlapped}
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
on:lock={() => lock(dataItem)}
|
||||
on:expand={() => {
|
||||
const parentGridItem = findGridItem($app, id)
|
||||
{#snippet children({ dataItem, overlapped, moveMode, componentDraggedId })}
|
||||
<ComponentWrapper
|
||||
id={dataItem.id}
|
||||
type={dataItem.data.type}
|
||||
class={classNames(
|
||||
'h-full w-full center-center',
|
||||
$selectedComponent?.includes(dataItem.id) ? 'active-grid-item' : '',
|
||||
'top-0'
|
||||
)}
|
||||
>
|
||||
<GridEditorMenu id={dataItem.id}>
|
||||
<Component
|
||||
{overlapped}
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
on:lock={() => lock(dataItem)}
|
||||
on:expand={() => {
|
||||
const parentGridItem = findGridItem(app, id)
|
||||
|
||||
if (!parentGridItem) {
|
||||
return
|
||||
}
|
||||
if (!parentGridItem) {
|
||||
return
|
||||
}
|
||||
|
||||
$selectedComponent = [dataItem.id]
|
||||
push(editorContext?.history, $app)
|
||||
$selectedComponent = [dataItem.id]
|
||||
push(editorContext?.history, app)
|
||||
|
||||
expandGriditem(
|
||||
$app.subgrids?.[subGridId] ?? [],
|
||||
dataItem.id,
|
||||
$breakpoint,
|
||||
parentGridItem
|
||||
)
|
||||
// $app = $app
|
||||
}}
|
||||
on:fillHeight={() => {
|
||||
const gridItem = findGridItem($app, dataItem.id)
|
||||
const b = $breakpoint === 'sm' ? 3 : 12
|
||||
expandGriditem(
|
||||
app.subgrids?.[subGridId] ?? [],
|
||||
dataItem.id,
|
||||
$breakpoint,
|
||||
parentGridItem
|
||||
)
|
||||
// $app = $app
|
||||
}}
|
||||
on:fillHeight={() => {
|
||||
const gridItem = findGridItem(app, dataItem.id)
|
||||
const b = $breakpoint === 'sm' ? 3 : 12
|
||||
|
||||
if (gridItem?.[b]) {
|
||||
gridItem[b].fullHeight = !gridItem[b].fullHeight
|
||||
}
|
||||
// $app = $app
|
||||
}}
|
||||
{moveMode}
|
||||
{componentDraggedId}
|
||||
/>
|
||||
</GridEditorMenu>
|
||||
</ComponentWrapper>
|
||||
if (gridItem?.[b]) {
|
||||
gridItem[b].fullHeight = !gridItem[b].fullHeight
|
||||
}
|
||||
// $app = $app
|
||||
}}
|
||||
{moveMode}
|
||||
{componentDraggedId}
|
||||
/>
|
||||
</GridEditorMenu>
|
||||
</ComponentWrapper>
|
||||
{/snippet}
|
||||
</Grid>
|
||||
</div>
|
||||
{:else}
|
||||
<GridViewer
|
||||
allIdsInPath={$allIdsInPath}
|
||||
items={$app.subgrids?.[subGridId] ?? []}
|
||||
let:dataItem
|
||||
items={app.subgrids?.[subGridId] ?? []}
|
||||
breakpoint={$breakpoint}
|
||||
parentWidth={$parentWidth - 17}
|
||||
{containerWidth}
|
||||
{maxRow}
|
||||
>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
on:pointerdown|stopPropagation={(e) => selectComponent(e, dataItem.id)}
|
||||
class={classNames('h-full w-full center-center', 'top-0')}
|
||||
>
|
||||
<Component
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
/>
|
||||
</div>
|
||||
{#snippet children({ dataItem })}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
onpointerdown={(e) => {
|
||||
e.stopPropagation()
|
||||
selectComponent(e, dataItem.id)
|
||||
}}
|
||||
class={classNames('h-full w-full center-center', 'top-0')}
|
||||
>
|
||||
<Component
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
/>
|
||||
</div>
|
||||
{/snippet}
|
||||
</GridViewer>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{:else if $app.lazyInitRequire == undefined}
|
||||
{#each $app?.subgrids?.[subGridId] ?? [] as item}
|
||||
{:else if app.lazyInitRequire == undefined}
|
||||
{#each app?.subgrids?.[subGridId] ?? [] as item}
|
||||
<Component selected={false} fullHeight={false} render={false} component={item.data} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -94,7 +94,11 @@
|
||||
}: Props = $props()
|
||||
</script>
|
||||
|
||||
<svelte:boundary>
|
||||
<svelte:boundary
|
||||
onerror={(e) => {
|
||||
console.log(`error in rendering component ${component.id}`, e)
|
||||
}}
|
||||
>
|
||||
{#if component.type === 'displaycomponent'}
|
||||
<AppDisplayComponent
|
||||
id={component.id}
|
||||
|
||||
@@ -91,9 +91,9 @@
|
||||
title={name}
|
||||
prefix={TITLE_PREFIX}
|
||||
on:open={(e) => {
|
||||
if ($app.css != undefined) {
|
||||
if (type && e.detail && $app.css[type] == undefined) {
|
||||
$app.css[type] = Object.fromEntries((ids ?? []).map(({ id }) => [id, {}]))
|
||||
if (app.css != undefined) {
|
||||
if (type && e.detail && app.css[type] == undefined) {
|
||||
app.css[type] = Object.fromEntries((ids ?? []).map(({ id }) => [id, {}]))
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let cssEditor: SimpleEditor | undefined = undefined
|
||||
let alertHeight: number | undefined = undefined
|
||||
let themeViewer: any = undefined
|
||||
let selectedTab: 'css' | 'theme' = 'css'
|
||||
let cssEditor: SimpleEditor | undefined = $state(undefined)
|
||||
let alertHeight: number | undefined = $state(undefined)
|
||||
let themeViewer: any = $state(undefined)
|
||||
let selectedTab: 'css' | 'theme' = $state('css')
|
||||
|
||||
function insertSelector(selector: string) {
|
||||
if ($app?.theme?.type === 'path') {
|
||||
if (app?.theme?.type === 'path') {
|
||||
sendUserToast(
|
||||
'You cannot edit the theme because it is a path theme. Fork the theme to edit it.',
|
||||
true
|
||||
@@ -70,25 +70,25 @@
|
||||
</div>
|
||||
{/if}
|
||||
<div style="height: calc(100% - {alertHeight || 0}px);">
|
||||
{#if $app.theme?.type === 'inlined'}
|
||||
{#if app.theme?.type === 'inlined'}
|
||||
<SimpleEditor
|
||||
class="h-full"
|
||||
lang="css"
|
||||
bind:code={$app.theme.css}
|
||||
bind:code={app.theme.css}
|
||||
fixedOverflowWidgets={true}
|
||||
small
|
||||
automaticLayout
|
||||
bind:this={cssEditor}
|
||||
/>
|
||||
{:else}
|
||||
<ThemeCodePreview theme={$app.theme}>
|
||||
<ThemeCodePreview theme={app.theme}>
|
||||
<div class="p-2 w-min">
|
||||
<Button
|
||||
size="xs"
|
||||
color="dark"
|
||||
on:click={async () => {
|
||||
const theme = await resolveTheme($app.theme, $workspaceStore)
|
||||
$app.theme = {
|
||||
const theme = await resolveTheme(app.theme, $workspaceStore)
|
||||
app.theme = {
|
||||
type: 'inlined',
|
||||
css: theme
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
|
||||
function getSubgrids(item: GridItem) {
|
||||
let allSubgrids = {}
|
||||
let subgrids = getAllSubgridsAndComponentIds($app, item.data)[0]
|
||||
let subgrids = getAllSubgridsAndComponentIds(app, item.data)[0]
|
||||
for (let key of subgrids) {
|
||||
allSubgrids[key] = $app.subgrids?.[key]
|
||||
allSubgrids[key] = app.subgrids?.[key]
|
||||
}
|
||||
return allSubgrids
|
||||
}
|
||||
|
||||
@@ -116,17 +116,17 @@
|
||||
function collectStyles() {
|
||||
const styles: string[] = []
|
||||
// Getting global app styles
|
||||
Object.values($app.css || {}).forEach((element) => {
|
||||
Object.values(app.css || {}).forEach((element) => {
|
||||
Object.values(element).filter(({ style }) => style && styles.push(style))
|
||||
})
|
||||
// Getting styles from individual components
|
||||
$app.grid.map((component) => {
|
||||
app.grid.map((component) => {
|
||||
Object.values(component.data.customCss || {}).forEach(({ style }) => {
|
||||
style && styles.push(style)
|
||||
})
|
||||
})
|
||||
// Getting style from subgrids
|
||||
Object.values($app.subgrids || {}).forEach((grid) => {
|
||||
Object.values(app.subgrids || {}).forEach((grid) => {
|
||||
grid.map((component) => {
|
||||
Object.values(component.data.customCss || {}).forEach(({ style }) => {
|
||||
style && styles.push(style)
|
||||
@@ -193,7 +193,7 @@
|
||||
mounted && (!value || value) && untrack(() => parseStyle())
|
||||
})
|
||||
$effect(() => {
|
||||
$app && untrack(() => setTopColors())
|
||||
app && untrack(() => setTopColors())
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
|
||||
const { previewTheme, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let cssString: string | undefined = $app?.theme?.type === 'inlined' ? $app.theme.css : undefined
|
||||
$: type = $app?.theme?.type
|
||||
let cssString: string | undefined = app?.theme?.type === 'inlined' ? app.theme.css : undefined
|
||||
let type = $derived(app?.theme?.type)
|
||||
|
||||
let themes: Array<{
|
||||
name: string
|
||||
path: string
|
||||
}> = []
|
||||
}> = $state([])
|
||||
|
||||
let loading: boolean = false
|
||||
let loading: boolean = $state(false)
|
||||
|
||||
async function getThemes() {
|
||||
loading = true
|
||||
@@ -56,14 +56,14 @@
|
||||
|
||||
sendUserToast('Theme created:' + message)
|
||||
|
||||
$app.theme = {
|
||||
app.theme = {
|
||||
type: 'path',
|
||||
path: theme.path
|
||||
}
|
||||
}
|
||||
|
||||
let nameField: string = ''
|
||||
let previewThemePath: string | undefined = undefined
|
||||
let nameField: string = $state('')
|
||||
let previewThemePath: string | undefined = $state(undefined)
|
||||
|
||||
onMount(() => {
|
||||
getThemes()
|
||||
|
||||
@@ -16,17 +16,20 @@
|
||||
import ThemeDrawer from './ThemeDrawer.svelte'
|
||||
import Dropdown from '$lib/components/DropdownV2.svelte'
|
||||
|
||||
export let previewThemePath: string | undefined = undefined
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
interface Props {
|
||||
previewThemePath?: string | undefined
|
||||
row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
}
|
||||
|
||||
const { previewTheme, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
let { previewThemePath = $bindable(undefined), row }: Props = $props()
|
||||
|
||||
let cssString: string | undefined = $app?.theme?.type === 'inlined' ? $app.theme.css : undefined
|
||||
$: type = $app?.theme?.type
|
||||
const { previewTheme, app } = $state(getContext<AppViewerContext>('AppViewerContext'))
|
||||
|
||||
let cssString: string | undefined = app?.theme?.type === 'inlined' ? app.theme.css : undefined
|
||||
let type = $derived(app?.theme?.type)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -41,7 +44,7 @@
|
||||
}
|
||||
})
|
||||
|
||||
$app.theme = {
|
||||
app.theme = {
|
||||
type: 'path',
|
||||
path: row.path
|
||||
}
|
||||
@@ -71,7 +74,7 @@
|
||||
})
|
||||
|
||||
stopPreview()
|
||||
$app.theme = {
|
||||
app.theme = {
|
||||
type: 'path',
|
||||
path: DEFAULT_THEME
|
||||
}
|
||||
@@ -111,7 +114,7 @@
|
||||
|
||||
const resolvedTheme = await resolveTheme(theme, $workspaceStore)
|
||||
|
||||
$app.theme = {
|
||||
app.theme = {
|
||||
type: 'inlined',
|
||||
css: resolvedTheme
|
||||
}
|
||||
@@ -126,7 +129,7 @@
|
||||
|
||||
function apply() {
|
||||
stopPreview()
|
||||
$app.theme = {
|
||||
app.theme = {
|
||||
type: 'path',
|
||||
path: row.path ?? ''
|
||||
}
|
||||
@@ -162,7 +165,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
let themeDrawer: ThemeDrawer
|
||||
let themeDrawer: ThemeDrawer | undefined = $state(undefined)
|
||||
</script>
|
||||
|
||||
<tr class={twMerge(previewThemePath === row.path ? 'bg-blue-200' : '', 'transition-all')}>
|
||||
@@ -179,7 +182,7 @@
|
||||
<Badge color="blue" small>Default</Badge>
|
||||
{/if}
|
||||
|
||||
{#if $app?.theme?.type === 'path' && $app.theme.path === row.path}
|
||||
{#if app?.theme?.type === 'path' && app.theme.path === row.path}
|
||||
<Badge color="green" small>Active</Badge>
|
||||
{/if}
|
||||
|
||||
@@ -193,7 +196,7 @@
|
||||
Update
|
||||
</Button>
|
||||
{/if}
|
||||
{#if $app?.theme?.type !== 'path' || $app.theme.path !== row.path}
|
||||
{#if app?.theme?.type !== 'path' || app.theme.path !== row.path}
|
||||
<Button color="light" size="xs" on:click={preview} startIcon={{ icon: Eye }}>
|
||||
Preview
|
||||
</Button>
|
||||
|
||||
@@ -12,34 +12,38 @@
|
||||
|
||||
const { app, initialized } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
$: unintitializedComponents = allItems($app.grid, $app.subgrids)
|
||||
.map((x) => x.id)
|
||||
.filter((x) => !$initialized.initializedComponents?.includes(x))
|
||||
.sort()
|
||||
let unintitializedComponents = $derived(
|
||||
allItems(app.grid, app.subgrids)
|
||||
.map((x) => x.id)
|
||||
.filter((x) => !$initialized.initializedComponents?.includes(x))
|
||||
.sort()
|
||||
)
|
||||
|
||||
$: subgridsErrors = Object.keys($app.subgrids ?? {})
|
||||
.map((x) => {
|
||||
const parentId = x.split('-')[0]
|
||||
const parent = findGridItem($app, parentId)
|
||||
const subgrid = x.replace(`${parentId}-`, '')
|
||||
if (subgrid == '-1') {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Invalid subgrid index -1 '
|
||||
let subgridsErrors = $derived(
|
||||
Object.keys(app.subgrids ?? {})
|
||||
.map((x) => {
|
||||
const parentId = x.split('-')[0]
|
||||
const parent = findGridItem(app, parentId)
|
||||
const subgrid = x.replace(`${parentId}-`, '')
|
||||
if (subgrid == '-1') {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Invalid subgrid index -1 '
|
||||
}
|
||||
} else if (parent === undefined) {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Parent not found'
|
||||
}
|
||||
} else if (parent?.data?.numberOfSubgrids === undefined) {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Parent is not a container'
|
||||
}
|
||||
}
|
||||
} else if (parent === undefined) {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Parent not found'
|
||||
}
|
||||
} else if (parent?.data?.numberOfSubgrids === undefined) {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Parent is not a container'
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
})
|
||||
.filter(Boolean)
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-8" style="all:none;">
|
||||
@@ -79,7 +83,7 @@
|
||||
|
||||
<!-- Iterate over uninitializedComponents to display each component in the grid -->
|
||||
{#each unintitializedComponents as c}
|
||||
{@const item = findGridItem($app, c)}
|
||||
{@const item = findGridItem(app, c)}
|
||||
{#if !item}
|
||||
<div>Item {c} not found</div>
|
||||
{:else}
|
||||
@@ -107,8 +111,8 @@
|
||||
}}
|
||||
size="xs2"
|
||||
on:click={() => {
|
||||
let parent = findGridItemParentGrid($app, c)
|
||||
deleteGridItem($app, item.data, parent) // $app = $app
|
||||
let parent = findGridItemParentGrid(app, c)
|
||||
deleteGridItem(app, item.data, parent) // $app = $app
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
@@ -162,9 +166,8 @@
|
||||
}}
|
||||
size="xs2"
|
||||
on:click={() => {
|
||||
if ($app.subgrids && s) {
|
||||
delete $app.subgrids[s.subGridId]
|
||||
$app = { ...$app }
|
||||
if (app.subgrids && s) {
|
||||
delete app.subgrids[s.subGridId]
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
let code = $state(JSON.stringify($app.lazyInitRequire))
|
||||
let code = $state(JSON.stringify(app.lazyInitRequire))
|
||||
|
||||
let selectedRendering = $state(
|
||||
$app.eagerRendering ? 'eager' : $app.lazyInitRequire ? 'lazy' : 'semi-lazy'
|
||||
app.eagerRendering ? 'eager' : app.lazyInitRequire ? 'lazy' : 'semi-lazy'
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -32,15 +32,15 @@
|
||||
bind:selected={selectedRendering}
|
||||
on:selected={(e) => {
|
||||
if (e.detail == 'eager') {
|
||||
$app.eagerRendering = true
|
||||
$app.lazyInitRequire = undefined
|
||||
app.eagerRendering = true
|
||||
app.lazyInitRequire = undefined
|
||||
} else if (e.detail == 'semi-lazy') {
|
||||
$app.eagerRendering = undefined
|
||||
$app.lazyInitRequire = undefined
|
||||
app.eagerRendering = undefined
|
||||
app.lazyInitRequire = undefined
|
||||
} else {
|
||||
$app.eagerRendering = undefined
|
||||
$app.lazyInitRequire = []
|
||||
code = JSON.stringify($app.lazyInitRequire)
|
||||
app.eagerRendering = undefined
|
||||
app.lazyInitRequire = []
|
||||
code = JSON.stringify(app.lazyInitRequire)
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -65,7 +65,7 @@
|
||||
</Section>
|
||||
{:else if selectedRendering == 'lazy'}
|
||||
<Section label="Component ids to wait the initialization of before the initial refresh">
|
||||
<JsonEditor bind:value={$app.lazyInitRequire} {code} />
|
||||
<JsonEditor bind:value={app.lazyInitRequire} {code} />
|
||||
<span class="text-tertiary text-xs">
|
||||
{'e.g: ["a", "b"]'}, no need to put background runnables ids
|
||||
</span>
|
||||
|
||||
@@ -7,18 +7,24 @@
|
||||
|
||||
const { connectingInput } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
export let id: string
|
||||
export let first: boolean = false
|
||||
export let label: string
|
||||
export let renderRec: boolean
|
||||
interface Props {
|
||||
id: string
|
||||
first?: boolean
|
||||
label: string
|
||||
renderRec: boolean
|
||||
}
|
||||
|
||||
let { id, first = false, label, renderRec }: Props = $props()
|
||||
</script>
|
||||
|
||||
<OutputHeader render={renderRec} let:render renamable={false} {id} name={label} {first}>
|
||||
<ComponentOutputViewer
|
||||
{render}
|
||||
componentId={id}
|
||||
on:select={({ detail }) => {
|
||||
$connectingInput = connectInput($connectingInput, id, detail)
|
||||
}}
|
||||
/>
|
||||
<OutputHeader render={renderRec} renamable={false} {id} name={label} {first}>
|
||||
{#snippet children({ render })}
|
||||
<ComponentOutputViewer
|
||||
{render}
|
||||
componentId={id}
|
||||
on:select={({ detail }) => {
|
||||
$connectingInput = connectInput($connectingInput, id, detail)
|
||||
}}
|
||||
/>
|
||||
{/snippet}
|
||||
</OutputHeader>
|
||||
|
||||
+1
-2
@@ -30,8 +30,7 @@
|
||||
stateId,
|
||||
worldStore,
|
||||
state: stateStore,
|
||||
appPath,
|
||||
app
|
||||
appPath
|
||||
} = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
interface Props {
|
||||
|
||||
+8
-4
@@ -6,9 +6,13 @@
|
||||
import type { Runnable, StaticAppInput } from '../../inputType'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
|
||||
export let runnable: HiddenRunnable
|
||||
export let id: string
|
||||
export let transformer: boolean
|
||||
interface Props {
|
||||
runnable: HiddenRunnable
|
||||
id: string
|
||||
transformer: boolean
|
||||
}
|
||||
|
||||
let { runnable = $bindable(), id, transformer }: Props = $props()
|
||||
|
||||
const { runnableComponents, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
async function fork(nrunnable: Runnable) {
|
||||
@@ -69,7 +73,7 @@
|
||||
/>
|
||||
{:else}
|
||||
<EmptyInlineScript
|
||||
unusedInlineScripts={$app?.unusedInlineScripts}
|
||||
unusedInlineScripts={app?.unusedInlineScripts}
|
||||
on:pick={(e) => onPick(e.detail)}
|
||||
on:delete
|
||||
showScriptPicker
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
}
|
||||
|
||||
function appendMigrationsToCss(migrations: Map<string, string[]>) {
|
||||
const theme = $app.theme
|
||||
const theme = app.theme
|
||||
|
||||
if (theme?.type === 'path') {
|
||||
sendUserToast(
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
theme.css = cssString
|
||||
|
||||
$app.theme = theme
|
||||
app.theme = theme
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
</Badge>
|
||||
</div>
|
||||
{/if}
|
||||
{#if component?.type && $app.css}
|
||||
{#if component?.type && app.css}
|
||||
{#each Object.keys(component.customCss ?? {}) as cssKey}
|
||||
{#if component.customCss?.[cssKey].style != undefined && component.customCss[cssKey].style !== ''}
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@@ -215,15 +215,15 @@
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if hasStyles(component?.type ? $app.css?.[component?.type] : undefined)}
|
||||
{#if hasStyles(component?.type ? app.css?.[component?.type] : undefined)}
|
||||
<div class="leading-6 text-xs font-semibold">
|
||||
Global: {component?.type ? ccomponents[component.type]?.name : ''}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if component?.type && $app.css}
|
||||
{#each Object.keys($app.css[component?.type] ?? {}) as cssKey}
|
||||
{#if type && $app.css?.[type]?.[cssKey].style != undefined && $app.css[type]?.[cssKey].style !== ''}
|
||||
{#if component?.type && app.css}
|
||||
{#each Object.keys(app.css[component?.type] ?? {}) as cssKey}
|
||||
{#if type && app.css?.[type]?.[cssKey].style != undefined && app.css[type]?.[cssKey].style !== ''}
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<div class="flex flex-row justify-between items-center py-0.5">
|
||||
@@ -236,9 +236,9 @@
|
||||
color="dark"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
if (type && $app.css?.[type]) {
|
||||
setOrUpdateMigration(cssKey, $app.css[type][cssKey].style)
|
||||
$app.css[type][cssKey].style = ''
|
||||
if (type && app.css?.[type]) {
|
||||
setOrUpdateMigration(cssKey, app.css[type][cssKey].style)
|
||||
app.css[type][cssKey].style = ''
|
||||
}
|
||||
}}
|
||||
endIcon={{ icon: MoveRight }}
|
||||
@@ -247,14 +247,14 @@
|
||||
</Button>
|
||||
</div>
|
||||
<div class="border p-2 rounded-md">
|
||||
<Highlight code={$app.css[type][cssKey].style} language={css} />
|
||||
<Highlight code={app.css[type][cssKey].style} language={css} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="leading-6 text-xs font-semibold my-1">Preview</div>
|
||||
<div class="border rounded-md p-2">
|
||||
<Highlight
|
||||
code={`${getSelector(cssKey)} {\n\t${$app.css[type][cssKey].style}\n}`}
|
||||
code={`${getSelector(cssKey)} {\n\t${app.css[type][cssKey].style}\n}`}
|
||||
language={css}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -7,29 +7,35 @@
|
||||
import typescript from 'svelte-highlight/languages/typescript'
|
||||
import { Button } from '$lib/components/common'
|
||||
import HighlightTheme from '$lib/components/HighlightTheme.svelte'
|
||||
export let type: keyof typeof components
|
||||
interface Props {
|
||||
type: keyof typeof components
|
||||
}
|
||||
|
||||
let { type }: Props = $props()
|
||||
|
||||
const componentControls = getComponentControl(type)
|
||||
|
||||
let collapsed: boolean = true
|
||||
let collapsed: boolean = $state(true)
|
||||
</script>
|
||||
|
||||
<HighlightTheme />
|
||||
|
||||
{#if componentControls?.length > 0}
|
||||
<PanelSection title="Controls">
|
||||
<div slot="action" class="flex justify-end flex-wrap gap-1">
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
btnClasses="text-2xs font-normal"
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}
|
||||
>
|
||||
{collapsed ? 'Show' : 'Hide'} details
|
||||
</Button>
|
||||
</div>
|
||||
{#snippet action()}
|
||||
<div class="flex justify-end flex-wrap gap-1">
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
btnClasses="text-2xs font-normal"
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}
|
||||
>
|
||||
{collapsed ? 'Show' : 'Hide'} details
|
||||
</Button>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
{#if collapsed}
|
||||
<div class="flex flex-row gap-1 flex-wrap">
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
let { componentInput = $bindable(), disableStatic = false, evalV2editor }: Props = $props()
|
||||
|
||||
const { onchange, connectingInput, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { onchange, connectingInput } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
function addGridItemContext(parentId: string) {
|
||||
if (!parentId) return
|
||||
const gridItem = findGridItem($app, parentId)
|
||||
const gridItem = findGridItem(app, parentId)
|
||||
addParentContextVariable(gridItem)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
function findParentsContextVariables(id: string): void {
|
||||
if (!id) return
|
||||
const allParents = dfs($app.grid, id, $app.subgrids ?? {})
|
||||
const allParents = dfs(app.grid, id, app.subgrids ?? {})
|
||||
|
||||
if (!allParents) return
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
export function removeGridElement() {
|
||||
const id = $selectedComponent?.[0]
|
||||
const componentSetting = findComponentSettings($app, id)
|
||||
push(history, $app)
|
||||
const componentSetting = findComponentSettings(app, id)
|
||||
push(history, app)
|
||||
|
||||
const onDeleteComponentControl = id ? $componentControl[id]?.onDelete : undefined
|
||||
if (onDeleteComponentControl) {
|
||||
@@ -44,7 +44,7 @@
|
||||
$selectedComponent = undefined
|
||||
$focusedGrid = undefined
|
||||
if (componentSetting?.item && !noGrid) {
|
||||
let ids = deleteGridItem($app, componentSetting?.item.data, componentSetting?.parent)
|
||||
let ids = deleteGridItem(app, componentSetting?.item.data, componentSetting?.parent)
|
||||
for (const key of ids) {
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
|
||||
@@ -13,24 +13,32 @@
|
||||
import { deleteGridItem } from '../appUtils'
|
||||
import type { AppComponent } from '../component'
|
||||
|
||||
export let conditions: RichConfiguration[] = []
|
||||
export let component: AppComponent
|
||||
interface Props {
|
||||
conditions?: RichConfiguration[]
|
||||
component: AppComponent
|
||||
}
|
||||
|
||||
let items = conditions.slice(0, -1).map((condition, index) => {
|
||||
return { value: condition, id: generateRandomString(), originalIndex: index }
|
||||
let { conditions = $bindable([]), component = $bindable() }: Props = $props()
|
||||
|
||||
let items = $state(
|
||||
conditions.slice(0, -1).map((condition, index) => {
|
||||
return { value: condition, id: generateRandomString(), originalIndex: index }
|
||||
})
|
||||
)
|
||||
|
||||
$effect.pre(() => {
|
||||
conditions = items
|
||||
.map((item) => item.value)
|
||||
.concat([
|
||||
{
|
||||
type: 'evalv2',
|
||||
expr: 'true',
|
||||
fieldType: 'boolean',
|
||||
connections: []
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
$: conditions = items
|
||||
.map((item) => item.value)
|
||||
.concat([
|
||||
{
|
||||
type: 'evalv2',
|
||||
expr: 'true',
|
||||
fieldType: 'boolean',
|
||||
connections: []
|
||||
}
|
||||
])
|
||||
|
||||
const { app, runnableComponents, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -49,7 +57,7 @@
|
||||
const newSubgrids = {}
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
newSubgrids[`${component.id}-${i}`] =
|
||||
$app!.subgrids![`${component.id}-${items[i].originalIndex}`] ?? []
|
||||
app!.subgrids![`${component.id}-${items[i].originalIndex}`] ?? []
|
||||
}
|
||||
|
||||
// update originalIndex
|
||||
@@ -57,8 +65,8 @@
|
||||
item.originalIndex = i
|
||||
})
|
||||
|
||||
$app!.subgrids = {
|
||||
...$app!.subgrids,
|
||||
app!.subgrids = {
|
||||
...app!.subgrids,
|
||||
...newSubgrids
|
||||
} // $app = $app
|
||||
|
||||
@@ -71,8 +79,8 @@
|
||||
|
||||
function deleteSubgrid(index: number) {
|
||||
let subgrid = `${component.id}-${index}`
|
||||
for (const item of $app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem($app, item.data, subgrid)
|
||||
for (const item of app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem(app, item.data, subgrid)
|
||||
for (const key in components) {
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
@@ -80,7 +88,7 @@
|
||||
|
||||
$runnableComponents = $runnableComponents
|
||||
for (let i = index; i < items.length; i++) {
|
||||
$app!.subgrids![`${component.id}-${i}`] = $app!.subgrids![`${component.id}-${i + 1}`]
|
||||
app!.subgrids![`${component.id}-${i}`] = app!.subgrids![`${component.id}-${i + 1}`]
|
||||
}
|
||||
|
||||
// Remove the corresponding item from the items array
|
||||
@@ -93,20 +101,20 @@
|
||||
})
|
||||
items = nitems
|
||||
|
||||
delete $app!.subgrids![`${component.id}-${items.length + 1}`] // $app = $app
|
||||
delete app!.subgrids![`${component.id}-${items.length + 1}`] // $app = $app
|
||||
}
|
||||
|
||||
function addCondition(): void {
|
||||
const numberOfConditions = conditions.length
|
||||
|
||||
if (!$app.subgrids) {
|
||||
$app.subgrids = {}
|
||||
if (!app.subgrids) {
|
||||
app.subgrids = {}
|
||||
}
|
||||
|
||||
$app.subgrids[`${component.id}-${numberOfConditions}`] =
|
||||
$app.subgrids[`${component.id}-${numberOfConditions - 1}`]
|
||||
app.subgrids[`${component.id}-${numberOfConditions}`] =
|
||||
app.subgrids[`${component.id}-${numberOfConditions - 1}`]
|
||||
|
||||
$app.subgrids[`${component.id}-${numberOfConditions - 1}`] = []
|
||||
app.subgrids[`${component.id}-${numberOfConditions - 1}`] = []
|
||||
|
||||
const newCondition: AppInputSpec<'boolean', boolean> = {
|
||||
type: 'evalv2',
|
||||
@@ -139,8 +147,8 @@
|
||||
flipDurationMs: 200,
|
||||
dropTargetStyle: {}
|
||||
}}
|
||||
on:consider={handleConsider}
|
||||
on:finalize={handleFinalize}
|
||||
onconsider={handleConsider}
|
||||
onfinalize={handleFinalize}
|
||||
>
|
||||
{#each items as item, index (item.id)}
|
||||
{@const condition = item.value}
|
||||
@@ -166,14 +174,14 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center gap-2">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div on:click={() => deleteSubgrid(index)}>
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div onclick={() => deleteSubgrid(index)}>
|
||||
<X size={16} />
|
||||
</div>
|
||||
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div use:dragHandle class="w-4 h-4 handle" aria-label="drag-handle">
|
||||
<GripVertical size={16} />
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createBubbler, stopPropagation } from 'svelte/legacy'
|
||||
|
||||
const bubble = createBubbler()
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import CloseButton from '$lib/components/common/CloseButton.svelte'
|
||||
import { getContext, tick } from 'svelte'
|
||||
@@ -11,27 +14,40 @@
|
||||
import { GripVertical, Plus } from 'lucide-svelte'
|
||||
import GridTabDisabled from './GridTabDisabled.svelte'
|
||||
|
||||
export let tabs: string[] = []
|
||||
export let disabledTabs: RichConfiguration[] = []
|
||||
|
||||
export let canDisableTabs: boolean = false
|
||||
|
||||
export let word: string = 'Tab'
|
||||
|
||||
export let component: AppComponent
|
||||
|
||||
$: if (disabledTabs == undefined) {
|
||||
disabledTabs = [
|
||||
{ type: 'static', value: false, fieldType: 'boolean' },
|
||||
{ type: 'static', value: false, fieldType: 'boolean' }
|
||||
]
|
||||
interface Props {
|
||||
tabs?: string[]
|
||||
disabledTabs?: RichConfiguration[]
|
||||
canDisableTabs?: boolean
|
||||
word?: string
|
||||
component: AppComponent
|
||||
}
|
||||
|
||||
let items = tabs.map((tab, index) => {
|
||||
return { value: tab, id: generateRandomString(), originalIndex: index }
|
||||
let {
|
||||
tabs = $bindable([]),
|
||||
disabledTabs = $bindable([]),
|
||||
canDisableTabs = false,
|
||||
word = 'Tab',
|
||||
component = $bindable()
|
||||
}: Props = $props()
|
||||
|
||||
$effect.pre(() => {
|
||||
if (disabledTabs == undefined) {
|
||||
disabledTabs = [
|
||||
{ type: 'static', value: false, fieldType: 'boolean' },
|
||||
{ type: 'static', value: false, fieldType: 'boolean' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
$: tabs = items.map((item) => item.value)
|
||||
let items = $state(
|
||||
tabs.map((tab, index) => {
|
||||
return { value: tab, id: generateRandomString(), originalIndex: index }
|
||||
})
|
||||
)
|
||||
|
||||
$effect.pre(() => {
|
||||
tabs = items.map((item) => item.value)
|
||||
})
|
||||
|
||||
const { app, runnableComponents, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -39,11 +55,11 @@
|
||||
function addTab() {
|
||||
const numberOfTabs = items.length
|
||||
|
||||
if (!$app.subgrids) {
|
||||
$app.subgrids = {}
|
||||
if (!app.subgrids) {
|
||||
app.subgrids = {}
|
||||
}
|
||||
|
||||
$app.subgrids[`${component.id}-${numberOfTabs}`] = []
|
||||
app.subgrids[`${component.id}-${numberOfTabs}`] = []
|
||||
items = [
|
||||
...items,
|
||||
{
|
||||
@@ -59,8 +75,8 @@
|
||||
|
||||
function deleteSubgrid(index: number) {
|
||||
let subgrid = `${component.id}-${index}`
|
||||
for (const item of $app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem($app, item.data, subgrid)
|
||||
for (const item of app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem(app, item.data, subgrid)
|
||||
for (const key in components) {
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
@@ -68,7 +84,7 @@
|
||||
$runnableComponents = $runnableComponents
|
||||
|
||||
for (let i = index; i < items.length - 1; i++) {
|
||||
$app!.subgrids![`${component.id}-${i}`] = $app!.subgrids![`${component.id}-${i + 1}`]
|
||||
app!.subgrids![`${component.id}-${i}`] = app!.subgrids![`${component.id}-${i + 1}`]
|
||||
}
|
||||
|
||||
// Remove the corresponding item from the items array
|
||||
@@ -84,7 +100,7 @@
|
||||
})
|
||||
items = items
|
||||
|
||||
delete $app!.subgrids![`${component.id}-${items.length}`] // $app = $app
|
||||
delete app!.subgrids![`${component.id}-${items.length}`] // $app = $app
|
||||
}
|
||||
|
||||
function handleConsider(e: CustomEvent): void {
|
||||
@@ -109,7 +125,7 @@
|
||||
const newSubgrids = {}
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
newSubgrids[`${component.id}-${i}`] =
|
||||
$app!.subgrids![`${component.id}-${items[i].originalIndex}`] ?? []
|
||||
app!.subgrids![`${component.id}-${items[i].originalIndex}`] ?? []
|
||||
}
|
||||
|
||||
const newDisabledTabs: RichConfiguration[] = []
|
||||
@@ -123,8 +139,8 @@
|
||||
item.originalIndex = i
|
||||
})
|
||||
|
||||
$app!.subgrids = {
|
||||
...$app!.subgrids,
|
||||
app!.subgrids = {
|
||||
...app!.subgrids,
|
||||
...newSubgrids
|
||||
} // $app = $app
|
||||
|
||||
@@ -147,15 +163,15 @@
|
||||
flipDurationMs: 200,
|
||||
dropTargetStyle: {}
|
||||
}}
|
||||
on:consider={handleConsider}
|
||||
on:finalize={handleFinalize}
|
||||
onconsider={handleConsider}
|
||||
onfinalize={handleFinalize}
|
||||
>
|
||||
{#each items as item, index (item.id)}
|
||||
<div class="border rounded-md p-2 mb-2 bg-surface">
|
||||
<div class="w-full flex flex-row gap-2 items-center relative my-1">
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
on:input={(e) => updateItemValue(index, e)}
|
||||
onkeydown={stopPropagation(bubble('keydown'))}
|
||||
oninput={(e) => updateItemValue(index, e)}
|
||||
type="text"
|
||||
bind:value={items[index].value}
|
||||
/>
|
||||
@@ -164,9 +180,9 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center gap-2">
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div use:dragHandle class="handle w-4 h-4" aria-label="drag-handle">
|
||||
<GripVertical size={16} />
|
||||
</div>
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
export let components: (BaseAppComponent & ButtonComponent)[]
|
||||
export let id: string
|
||||
|
||||
const { selectedComponent, app, errorByComponent } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const { selectedComponent, errorByComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
function addComponent() {
|
||||
const actionId = getNextId(components.map((x) => x.id.split('_')[1]))
|
||||
|
||||
@@ -9,16 +9,22 @@
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
export let appInput: ResultAppInput
|
||||
export let appComponent: AppComponent
|
||||
|
||||
$: if (appInput.autoRefresh === undefined) {
|
||||
appInput.autoRefresh = true
|
||||
interface Props {
|
||||
appInput: ResultAppInput
|
||||
appComponent: AppComponent
|
||||
}
|
||||
|
||||
let { appInput = $bindable(), appComponent = $bindable() }: Props = $props()
|
||||
|
||||
$effect.pre(() => {
|
||||
if (appInput.autoRefresh === undefined) {
|
||||
appInput.autoRefresh = true
|
||||
}
|
||||
})
|
||||
|
||||
function detach() {
|
||||
if (appInput.runnable?.type === 'runnableByName' && appInput.runnable.inlineScript) {
|
||||
$app.unusedInlineScripts.push({
|
||||
app.unusedInlineScripts.push({
|
||||
name: appInput.runnable.name,
|
||||
inlineScript: appInput.runnable.inlineScript
|
||||
}) // $app = $app
|
||||
@@ -30,7 +36,7 @@
|
||||
appInput = clearResultAppInput(appInput)
|
||||
}
|
||||
|
||||
$: {
|
||||
$effect.pre(() => {
|
||||
if (appInput.recomputeOnInputChanged === undefined) {
|
||||
appInput.recomputeOnInputChanged = true
|
||||
}
|
||||
@@ -39,11 +45,13 @@
|
||||
appInput.recomputeOnInputChanged = !appInput.doNotRecomputeOnInputChanged
|
||||
appInput.doNotRecomputeOnInputChanged = undefined
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$: hasScript =
|
||||
let hasScript = $derived(
|
||||
appInput?.runnable?.type === 'runnableByPath' ||
|
||||
(appInput?.runnable?.type === 'runnableByName' && appInput.runnable?.inlineScript !== undefined)
|
||||
(appInput?.runnable?.type === 'runnableByName' &&
|
||||
appInput.runnable?.inlineScript !== undefined)
|
||||
)
|
||||
|
||||
function getActions(_hasScript: boolean): ActionType[] {
|
||||
return [
|
||||
@@ -66,7 +74,7 @@
|
||||
]
|
||||
}
|
||||
|
||||
$: actions = getActions(hasScript)
|
||||
let actions = $derived(getActions(hasScript))
|
||||
</script>
|
||||
|
||||
<ComponentScriptSettings bind:appInput bind:appComponent {hasScript} {actions} />
|
||||
|
||||
@@ -20,28 +20,29 @@
|
||||
|
||||
const { app, cssEditorOpen, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let component: AppComponent | undefined
|
||||
$: {
|
||||
const newComponent = findComponentSettings($app, $selectedComponent?.[0])?.item?.data
|
||||
let component: AppComponent | undefined = $state()
|
||||
$effect.pre(() => {
|
||||
const newComponent = findComponentSettings(app, $selectedComponent?.[0])?.item?.data
|
||||
if (component != newComponent) {
|
||||
component = newComponent
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let tab: 'local' | 'global' = 'local'
|
||||
let overrideGlobalCSS: (() => void) | undefined = undefined
|
||||
let overrideLocalCSS: (() => void) | undefined = undefined
|
||||
$: type = component?.type
|
||||
let migrationModal: CssMigrationModal | undefined = undefined
|
||||
let tab: 'local' | 'global' = $state('local')
|
||||
let overrideGlobalCSS: (() => void) | undefined = $state(undefined)
|
||||
let overrideLocalCSS: (() => void) | undefined = $state(undefined)
|
||||
let type = $derived(component?.type)
|
||||
let migrationModal: CssMigrationModal | undefined = $state(undefined)
|
||||
|
||||
$: customCssByComponentType =
|
||||
component?.type && $app.css
|
||||
? Object.entries($app.css[component.type] || {}).map(([id, v]) => ({
|
||||
let customCssByComponentType = $derived(
|
||||
component?.type && app.css
|
||||
? Object.entries(app.css[component.type] || {}).map(([id, v]) => ({
|
||||
id,
|
||||
forceStyle: v?.style != undefined,
|
||||
forceClass: v?.['class'] != undefined
|
||||
}))
|
||||
: undefined
|
||||
)
|
||||
|
||||
function copyLocalToGlobal(name: string, value: ComponentCssProperty | undefined) {
|
||||
if (!value) {
|
||||
@@ -51,18 +52,16 @@
|
||||
|
||||
if (!type) return
|
||||
|
||||
if (hasStyleValue($app.css?.[type]?.[name])) {
|
||||
if (hasStyleValue(app.css?.[type]?.[name])) {
|
||||
overrideGlobalCSS = () => {
|
||||
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
}
|
||||
} else {
|
||||
if (!$app.css![type]) {
|
||||
if (!app.css![type]) {
|
||||
initGlobalCss()
|
||||
}
|
||||
|
||||
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
sendUserToast('Global CSS copied')
|
||||
}
|
||||
}
|
||||
@@ -75,11 +74,9 @@
|
||||
if (hasStyleValue(value)) {
|
||||
overrideLocalCSS = () => {
|
||||
component!.customCss![id] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
}
|
||||
} else {
|
||||
component!.customCss![id] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
sendUserToast('Local CSS copied')
|
||||
}
|
||||
}
|
||||
@@ -88,21 +85,20 @@
|
||||
function initGlobalCss() {
|
||||
// If the global css is not initialised, we initialise it.
|
||||
// Should only happen once per app
|
||||
if (!$app.css) {
|
||||
$app.css = {}
|
||||
if (!app.css) {
|
||||
app.css = {}
|
||||
}
|
||||
|
||||
// If the global css for this component type is not initialised, we initialise it.
|
||||
// Should only happen once per component type
|
||||
if (
|
||||
$app.css &&
|
||||
app.css &&
|
||||
component &&
|
||||
!$app.css[component.type]?.style &&
|
||||
!app.css[component.type]?.style &&
|
||||
components[component.type] &&
|
||||
$app.css[component.type] === undefined
|
||||
app.css[component.type] === undefined
|
||||
) {
|
||||
$app.css[component.type] = JSON.parse(JSON.stringify(components[component.type].customCss))
|
||||
app.set($app)
|
||||
app.css[component.type] = JSON.parse(JSON.stringify(components[component.type].customCss))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,13 +192,12 @@
|
||||
wmClass={getSelector(name)}
|
||||
componentType={component.type}
|
||||
bind:value={component.customCss[name]}
|
||||
on:change={() => app.set($app)}
|
||||
shouldDisplayRight={hasStyleValue(component.customCss[name])}
|
||||
on:right={() => {
|
||||
copyLocalToGlobal(name, component?.customCss?.[name])
|
||||
tab = 'global'
|
||||
}}
|
||||
overridding={hasStyleValue($app.css?.[component.type]?.[name]) &&
|
||||
overridding={hasStyleValue(app.css?.[component.type]?.[name]) &&
|
||||
hasStyleValue(component.customCss[name])}
|
||||
/>
|
||||
</div>
|
||||
@@ -214,16 +209,16 @@
|
||||
{#if type}
|
||||
{#each customCssByComponentType ?? [] as { id, forceStyle, forceClass }}
|
||||
<div class="w-full">
|
||||
{#if $app.css && type && $app.css[type] && component?.customCss}
|
||||
{#if app.css && type && app.css[type] && component?.customCss}
|
||||
<CssPropertyWrapper
|
||||
{forceStyle}
|
||||
{forceClass}
|
||||
{id}
|
||||
bind:property={$app.css[type]}
|
||||
bind:property={app.css[type]}
|
||||
on:left={() => {
|
||||
copyGlobalToLocal(
|
||||
id,
|
||||
component?.type ? $app?.css?.[component?.type]?.[id] : undefined
|
||||
component?.type ? app?.css?.[component?.type]?.[id] : undefined
|
||||
)
|
||||
tab = 'local'
|
||||
}}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createBubbler } from 'svelte/legacy'
|
||||
|
||||
const bubble = createBubbler()
|
||||
import { Badge } from '$lib/components/common'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { getNextId } from '$lib/components/flows/idUtils'
|
||||
@@ -15,11 +18,15 @@
|
||||
import TableActionsWizard from '$lib/components/wizards/TableActionsWizard.svelte'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
|
||||
export let components:
|
||||
| (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[]
|
||||
| undefined
|
||||
interface Props {
|
||||
components:
|
||||
| (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[]
|
||||
| undefined
|
||||
actionsOrder?: RichConfiguration | undefined
|
||||
id: string
|
||||
}
|
||||
|
||||
export let actionsOrder: RichConfiguration | undefined = undefined
|
||||
let { components = $bindable(), actionsOrder = $bindable(undefined), id }: Props = $props()
|
||||
|
||||
// Migration code:
|
||||
onMount(() => {
|
||||
@@ -28,16 +35,17 @@
|
||||
}
|
||||
})
|
||||
|
||||
let items =
|
||||
let items = $state(
|
||||
components?.map((tab, index) => {
|
||||
return { value: tab, id: generateRandomString(), originalIndex: index }
|
||||
}) ?? []
|
||||
)
|
||||
|
||||
$: components = items.map((item) => item.value)
|
||||
$effect.pre(() => {
|
||||
components = items.map((item) => item.value)
|
||||
})
|
||||
|
||||
export let id: string
|
||||
|
||||
const { selectedComponent, app, errorByComponent, hoverStore } =
|
||||
const { selectedComponent, errorByComponent, hoverStore } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
function addComponent(typ: 'buttoncomponent' | 'checkboxcomponent' | 'selectcomponent') {
|
||||
@@ -97,9 +105,9 @@
|
||||
|
||||
{#if components}
|
||||
<PanelSection title={`Table Actions`}>
|
||||
<svelte:fragment slot="action">
|
||||
{#snippet action()}
|
||||
<TableActionsWizard bind:actionsOrder selectedId={$selectedComponent?.[0] ?? ''} {components}>
|
||||
<svelte:fragment slot="trigger">
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
@@ -111,9 +119,9 @@
|
||||
<ListOrdered size={16} />
|
||||
</div>
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</TableActionsWizard>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
{#if components.length == 0}
|
||||
<span class="text-xs text-tertiary">No action buttons</span>
|
||||
{/if}
|
||||
@@ -124,27 +132,27 @@
|
||||
flipDurationMs: 200,
|
||||
dropTargetStyle: {}
|
||||
}}
|
||||
on:consider={handleConsider}
|
||||
on:finalize={handleFinalize}
|
||||
onconsider={handleConsider}
|
||||
onfinalize={handleFinalize}
|
||||
>
|
||||
{#each items as item, index (item.id)}
|
||||
{@const component = items[index].value}
|
||||
|
||||
<div animate:flip={{ duration: 200 }} class="flex flex-row gap-2 items-center mb-2">
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
|
||||
<div
|
||||
class={classNames(
|
||||
'w-full text-xs text-semibold truncate py-1.5 px-2 cursor-pointer justify-between flex items-center border rounded-md',
|
||||
'bg-surface hover:bg-surface-hover focus:border-primary text-secondary'
|
||||
)}
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
$selectedComponent = [component.id]
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
onmouseover={() => {
|
||||
$hoverStore = component.id
|
||||
}}
|
||||
on:keypress
|
||||
onkeypress={bubble('keypress')}
|
||||
>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<Badge color="dark-indigo">
|
||||
|
||||
+8
-8
@@ -57,10 +57,10 @@
|
||||
|
||||
function addSubGrid() {
|
||||
const numberOfPanes = nodes.length
|
||||
if (!$app.subgrids) {
|
||||
$app.subgrids = {}
|
||||
if (!app.subgrids) {
|
||||
app.subgrids = {}
|
||||
}
|
||||
$app.subgrids[`${component.id}-${numberOfPanes}`] = []
|
||||
app.subgrids[`${component.id}-${numberOfPanes}`] = []
|
||||
|
||||
component.numberOfSubgrids = nodes.length + 1
|
||||
}
|
||||
@@ -68,22 +68,22 @@
|
||||
function deleteSubgrid(index: number) {
|
||||
let subgrid = `${component.id}-${index}`
|
||||
|
||||
if (!$app.subgrids![subgrid]) {
|
||||
if (!app.subgrids![subgrid]) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const item of $app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem($app, item.data, subgrid)
|
||||
for (const item of app!.subgrids![subgrid]) {
|
||||
const components = deleteGridItem(app, item.data, subgrid)
|
||||
for (const key in components) {
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
}
|
||||
$runnableComponents = $runnableComponents
|
||||
for (let i = index; i < nodes.length - 1; i++) {
|
||||
$app!.subgrids![`${component.id}-${i}`] = $app!.subgrids![`${component.id}-${i + 1}`]
|
||||
app!.subgrids![`${component.id}-${i}`] = app!.subgrids![`${component.id}-${i + 1}`]
|
||||
}
|
||||
nodes.splice(index, 1)
|
||||
delete $app!.subgrids![`${component.id}-${nodes.length}`]
|
||||
delete app!.subgrids![`${component.id}-${nodes.length}`]
|
||||
|
||||
nodes = nodes
|
||||
component.numberOfSubgrids = nodes.length // $app = $app
|
||||
|
||||
+2
-2
@@ -126,9 +126,9 @@
|
||||
bind:this={editor}
|
||||
lang="javascript"
|
||||
bind:code={
|
||||
() => componentInput.expr ?? '',
|
||||
() => componentInput?.expr ?? '',
|
||||
(e) => {
|
||||
if (componentInput.expr != e) {
|
||||
if (componentInput?.expr != e) {
|
||||
componentInput.expr = e
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -7,9 +7,13 @@
|
||||
import SelectedRunnable from '../SelectedRunnable.svelte'
|
||||
import type { AppEditorContext, AppViewerContext } from '$lib/components/apps/types'
|
||||
|
||||
export let appInput: ResultAppInput
|
||||
export let defaultUserInput = false
|
||||
export let appComponent: AppComponent
|
||||
interface Props {
|
||||
appInput: ResultAppInput
|
||||
defaultUserInput?: boolean
|
||||
appComponent: AppComponent
|
||||
}
|
||||
|
||||
let { appInput = $bindable(), defaultUserInput = false, appComponent }: Props = $props()
|
||||
|
||||
const { selectedComponentInEditor } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -34,7 +38,7 @@
|
||||
<SelectedRunnable {appComponent} bind:appInput />
|
||||
{:else if appInput !== undefined}
|
||||
<RunnableSelector
|
||||
unusedInlineScripts={$app.unusedInlineScripts}
|
||||
unusedInlineScripts={app.unusedInlineScripts}
|
||||
hideCreateScript={appComponent.type === 'flowstatuscomponent'}
|
||||
onlyFlow={appComponent.type === 'flowstatuscomponent'}
|
||||
{defaultUserInput}
|
||||
|
||||
+6
-2
@@ -4,11 +4,15 @@
|
||||
import { allItems } from '$lib/components/apps/utils'
|
||||
import { getContext } from 'svelte'
|
||||
|
||||
export let componentInput: StaticInput<{ id: string; index: number }>
|
||||
interface Props {
|
||||
componentInput: StaticInput<{ id: string; index: number }>
|
||||
}
|
||||
|
||||
let { componentInput = $bindable() }: Props = $props()
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const tabComponents = allItems($app.grid, $app.subgrids).filter(
|
||||
const tabComponents = allItems(app.grid, app.subgrids).filter(
|
||||
(component) =>
|
||||
component.data.type === 'tabscomponent' ||
|
||||
component.data.type === 'conditionalwrapper' ||
|
||||
|
||||
+39
-22
@@ -4,24 +4,33 @@
|
||||
import { classNames, itemsExists } from '$lib/utils'
|
||||
import { Plus, X } from 'lucide-svelte'
|
||||
import { Button } from '$lib/components/common'
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import type { App, AppViewerContext, InlineScript } from '$lib/components/apps/types'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { getAllGridItems } from '../../../appUtils'
|
||||
|
||||
export let triggerEvents: string[] = []
|
||||
export let inlineScript: InlineScript | undefined = undefined
|
||||
export let isFrontend: boolean = false
|
||||
export let dependencies: string[] = []
|
||||
export let shoudlDisplayChangeEvents: boolean = false
|
||||
export let id: string
|
||||
interface Props {
|
||||
triggerEvents?: string[]
|
||||
inlineScript?: InlineScript | undefined
|
||||
isFrontend?: boolean
|
||||
dependencies?: string[]
|
||||
shoudlDisplayChangeEvents?: boolean
|
||||
id: string
|
||||
}
|
||||
|
||||
let {
|
||||
triggerEvents = [],
|
||||
inlineScript = $bindable(undefined),
|
||||
isFrontend = false,
|
||||
dependencies = [],
|
||||
shoudlDisplayChangeEvents = false,
|
||||
id
|
||||
}: Props = $props()
|
||||
|
||||
const { connectingInput, app, stateId } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let onSuccessEvents: string[] = []
|
||||
|
||||
$: computeOnSuccessEvents($app, id)
|
||||
let onSuccessEvents: string[] = $state([])
|
||||
|
||||
function computeOnSuccessEvents(app: App, _id: string) {
|
||||
const nr: string[] = []
|
||||
@@ -47,16 +56,6 @@
|
||||
})
|
||||
onSuccessEvents = nr
|
||||
}
|
||||
$: changeEvents = isFrontend
|
||||
? inlineScript?.refreshOn
|
||||
? inlineScript.refreshOn.map((x) => `${x.id}.${x.key}`)
|
||||
: []
|
||||
: dependencies
|
||||
|
||||
$: hasNoTriggers =
|
||||
triggerEvents.length === 0 &&
|
||||
(changeEvents.length === 0 || !shoudlDisplayChangeEvents) &&
|
||||
onSuccessEvents.length == 0
|
||||
|
||||
const badgeClass = 'inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium border'
|
||||
const colors = {
|
||||
@@ -86,6 +85,24 @@
|
||||
}
|
||||
inlineScript = inlineScript // $app = $app
|
||||
}
|
||||
$effect.pre(() => {
|
||||
;[app, id]
|
||||
untrack(() => {
|
||||
computeOnSuccessEvents(app, id)
|
||||
})
|
||||
})
|
||||
let changeEvents = $derived(
|
||||
isFrontend
|
||||
? inlineScript?.refreshOn
|
||||
? inlineScript.refreshOn.map((x) => `${x.id}.${x.key}`)
|
||||
: []
|
||||
: dependencies
|
||||
)
|
||||
let hasNoTriggers = $derived(
|
||||
triggerEvents.length === 0 &&
|
||||
(changeEvents.length === 0 || !shoudlDisplayChangeEvents) &&
|
||||
onSuccessEvents.length == 0
|
||||
)
|
||||
</script>
|
||||
|
||||
{#if hasNoTriggers}
|
||||
@@ -117,7 +134,7 @@
|
||||
{#if isFrontend}
|
||||
<button
|
||||
class="bg-blue-300 ml-2 p-0.5 rounded-md hover:bg-blue-400 cursor-pointer"
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (inlineScript?.refreshOn) {
|
||||
inlineScript.refreshOn = inlineScript.refreshOn.filter(
|
||||
(x) => `${x.id}.${x.key}` !== changeEvent
|
||||
@@ -172,7 +189,7 @@
|
||||
'p-0.5 rounded-md hover:bg-blue-400 cursor-pointer !text-2xs text-secondary',
|
||||
badgeClass
|
||||
)}
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (inlineScript) {
|
||||
if (!itemsExists(inlineScript.refreshOn, suggestion)) {
|
||||
inlineScript.refreshOn = [...(inlineScript.refreshOn ?? []), suggestion]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault, stopPropagation } from 'svelte/legacy'
|
||||
|
||||
import { createEventDispatcher, getContext, onMount } from 'svelte'
|
||||
import type { AppEditorContext, AppViewerContext } from '../types'
|
||||
import { writable } from 'svelte/store'
|
||||
@@ -13,33 +15,57 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let sensor
|
||||
export let width
|
||||
export let height
|
||||
export let left
|
||||
export let top
|
||||
interface Props {
|
||||
sensor: any
|
||||
width: any
|
||||
height: any
|
||||
left: any
|
||||
top: any
|
||||
id: any
|
||||
container: any
|
||||
xPerPx: any
|
||||
yPerPx: any
|
||||
gapX: any
|
||||
gapY: any
|
||||
item: any
|
||||
cols: any
|
||||
nativeContainer: any
|
||||
onTop: any
|
||||
shadow?: { x: number; y: number; w: number; h: number } | undefined
|
||||
overlapped?: string | undefined
|
||||
moveMode?: 'move' | 'insert'
|
||||
type?: string | undefined
|
||||
fakeShadow?: GridShadow | undefined
|
||||
disableMove?: boolean
|
||||
mounted?: boolean
|
||||
children?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
export let id
|
||||
export let container
|
||||
|
||||
export let xPerPx
|
||||
export let yPerPx
|
||||
|
||||
export let gapX
|
||||
export let gapY
|
||||
export let item
|
||||
|
||||
export let cols
|
||||
|
||||
export let nativeContainer
|
||||
export let onTop
|
||||
export let shadow: { x: number; y: number; w: number; h: number } | undefined = undefined
|
||||
export let overlapped: string | undefined = undefined
|
||||
export let moveMode: 'move' | 'insert' = 'move'
|
||||
export let type: string | undefined = undefined
|
||||
export let fakeShadow: GridShadow | undefined = undefined
|
||||
export let disableMove: boolean = true
|
||||
export let mounted: boolean = false
|
||||
let {
|
||||
sensor,
|
||||
width,
|
||||
height,
|
||||
left,
|
||||
top,
|
||||
id,
|
||||
container,
|
||||
xPerPx,
|
||||
yPerPx,
|
||||
gapX,
|
||||
gapY,
|
||||
item,
|
||||
cols,
|
||||
nativeContainer,
|
||||
onTop,
|
||||
shadow = $bindable(undefined),
|
||||
overlapped = undefined,
|
||||
moveMode = 'move',
|
||||
type = undefined,
|
||||
fakeShadow = undefined,
|
||||
disableMove = true,
|
||||
mounted = false,
|
||||
children
|
||||
}: Props = $props()
|
||||
|
||||
const ctx = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { mode, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -47,9 +73,9 @@
|
||||
const scale = ctx ? ctx.scale : writable(100)
|
||||
|
||||
const divId = `component-${id}`
|
||||
let shadowElement
|
||||
let shadowElement = $state(undefined) as HTMLElement | undefined
|
||||
|
||||
let active = false
|
||||
let active = $state(false)
|
||||
|
||||
let initX, initY
|
||||
|
||||
@@ -58,10 +84,10 @@
|
||||
y: 0
|
||||
}
|
||||
|
||||
let cordDiff = { x: 0, y: 0 }
|
||||
let cordDiff = $state({ x: 0, y: 0 })
|
||||
|
||||
let newSize = { width, height }
|
||||
let trans = false
|
||||
let newSize = $state({ width, height })
|
||||
let trans = $state(false)
|
||||
|
||||
let anima
|
||||
|
||||
@@ -114,6 +140,7 @@
|
||||
shadowBound = irect
|
||||
}
|
||||
|
||||
if (!rect) return
|
||||
const xdragBound = rect.left + cordDiff.x
|
||||
const ydragBound = rect.top + cordDiff.y
|
||||
|
||||
@@ -142,7 +169,7 @@
|
||||
// Autoscroll
|
||||
let _scrollTop = 0
|
||||
let containerFrame
|
||||
let rect
|
||||
let rect = $state() as { top: number; left: number } | undefined
|
||||
let scrollElement
|
||||
|
||||
const getContainerFrame = (element) => {
|
||||
@@ -317,7 +344,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let element: HTMLElement | undefined = undefined
|
||||
let element: HTMLElement | undefined = $state(undefined)
|
||||
|
||||
function computeShadow(clientX: number, clientY: number) {
|
||||
const elementsAtPoint = document.elementsFromPoint(clientX, clientY)
|
||||
@@ -384,7 +411,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
const parent = findGridItemParentGrid($app, id)
|
||||
const parent = findGridItemParentGrid(app, id)
|
||||
|
||||
if (overlapped && (overlapped === parent || parent?.startsWith(overlapped))) {
|
||||
return
|
||||
@@ -469,7 +496,7 @@
|
||||
return true
|
||||
}
|
||||
|
||||
const parent = findGridItemParentGrid($app, id)
|
||||
const parent = findGridItemParentGrid(app, id)
|
||||
|
||||
if (parent === undefined) {
|
||||
return overlapped === undefined
|
||||
@@ -481,12 +508,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
bind:this={element}
|
||||
draggable="false"
|
||||
on:pointerdown|stopPropagation|preventDefault={pointerdown}
|
||||
onpointerdown={(e) => stopPropagation(preventDefault((_) => pointerdown(e)))}
|
||||
id={divId}
|
||||
class="svlt-grid-item"
|
||||
data-iscontainer={type ? isContainer(type) : false}
|
||||
@@ -495,30 +522,26 @@
|
||||
style="width: {xPerPx == 0 ? 0 : active ? newSize.width : width}px; height:{xPerPx == 0
|
||||
? 0
|
||||
: active
|
||||
? newSize.height
|
||||
: height}px;
|
||||
? newSize.height
|
||||
: height}px;
|
||||
{xPerPx == 0 ? 'overflow: hidden;' : ''}
|
||||
{onTop ? 'z-index: 1000;' : ''}
|
||||
|
||||
{active && rect
|
||||
? `transform: translate(${cordDiff.x}px, ${cordDiff.y}px);top:${rect.top}px;left:${rect.left}px;z-index:10000;`
|
||||
: trans
|
||||
? `transform: translate(${cordDiff.x}px, ${cordDiff.y}px); position:absolute; transition: width 0.2s, height 0.2s;`
|
||||
: `${
|
||||
xPerPx > 0 && mounted ? 'transition: transform 0.1s, opacity 0.1s;' : ''
|
||||
} transform: translate(${left}px, ${top}px); `} "
|
||||
? `transform: translate(${cordDiff.x}px, ${cordDiff.y}px); position:absolute; transition: width 0.2s, height 0.2s;`
|
||||
: `${
|
||||
xPerPx > 0 && mounted ? 'transition: transform 0.1s, opacity 0.1s;' : ''
|
||||
} transform: translate(${left}px, ${top}px); `} "
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
{#if moveMode === 'move' && !disableMove}
|
||||
<div
|
||||
class="svlt-grid-resizer-bottom"
|
||||
on:pointerdown={(e) => resizePointerDown(e, 'vertical')}
|
||||
<div class="svlt-grid-resizer-bottom" onpointerdown={(e) => resizePointerDown(e, 'vertical')}
|
||||
></div>
|
||||
<div
|
||||
class="svlt-grid-resizer-side"
|
||||
on:pointerdown={(e) => resizePointerDown(e, 'horizontal')}
|
||||
<div class="svlt-grid-resizer-side" onpointerdown={(e) => resizePointerDown(e, 'horizontal')}
|
||||
></div>
|
||||
<div class="svlt-grid-resizer" on:pointerdown={(e) => resizePointerDown(e, 'both')}></div>
|
||||
<div class="svlt-grid-resizer" onpointerdown={(e) => resizePointerDown(e, 'both')}></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
import type { Runnable } from '../apps/inputType'
|
||||
import { getNextId } from '$lib/components/flows/idUtils'
|
||||
|
||||
export let selectedRunnable: string | undefined
|
||||
export let runnables: Writable<Record<string, Runnable>>
|
||||
interface Props {
|
||||
selectedRunnable: string | undefined
|
||||
runnables: Writable<Record<string, Runnable>>
|
||||
}
|
||||
|
||||
let { selectedRunnable = $bindable(), runnables }: Props = $props()
|
||||
|
||||
function createBackgroundScript() {
|
||||
const nid = getNextId(Object.keys($runnables ?? {}))
|
||||
@@ -23,7 +27,6 @@
|
||||
}
|
||||
return r
|
||||
})
|
||||
console.log('BAR 2')
|
||||
selectedRunnable = nid
|
||||
}
|
||||
|
||||
@@ -31,7 +34,7 @@
|
||||
</script>
|
||||
|
||||
<PanelSection title="Backend Runnables" id="app-editor-runnable-panel">
|
||||
<svelte:fragment slot="action">
|
||||
{#snippet action()}
|
||||
<div class="flex flex-row gap-1">
|
||||
<HideButton
|
||||
direction="bottom"
|
||||
@@ -55,7 +58,7 @@
|
||||
<Plus size={14} class="!text-primary" />
|
||||
</Button>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
<div class="w-full flex flex-col gap-6 py-1">
|
||||
<div>
|
||||
<div class="flex flex-col gap-1 w-full">
|
||||
@@ -68,7 +71,7 @@
|
||||
{selectedRunnable === id
|
||||
? 'border-blue-500 bg-blue-100 dark:bg-frost-900/50'
|
||||
: 'hover:bg-blue-50 dark:hover:bg-frost-900/50'}"
|
||||
on:click={() => (selectedRunnable = id)}
|
||||
onclick={() => (selectedRunnable = id)}
|
||||
>
|
||||
<span class="text-2xs truncate">{runnable?.name}</span>
|
||||
<Badge color="indigo">{id}</Badge>
|
||||
|
||||
@@ -8,10 +8,14 @@
|
||||
import { clickButtonBySelector } from '../utils'
|
||||
import { updateProgress } from '$lib/tutorialUtils'
|
||||
|
||||
export let name: string
|
||||
export let index: number
|
||||
interface Props {
|
||||
name: string
|
||||
index: number
|
||||
}
|
||||
|
||||
let tutorial: Tutorial | undefined = undefined
|
||||
let { name, index }: Props = $props()
|
||||
|
||||
let tutorial: Tutorial | undefined = $state(undefined)
|
||||
|
||||
const { app, selectedComponent, focusedGrid } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { history } = getContext<AppEditorContext>('AppEditorContext')
|
||||
@@ -21,10 +25,10 @@
|
||||
}
|
||||
|
||||
function addComponent(): void {
|
||||
push(history, $app)
|
||||
push(history, app)
|
||||
|
||||
const id = insertNewGridItem(
|
||||
$app,
|
||||
app,
|
||||
appComponentFromType('textcomponent') as (id: string) => AppComponent,
|
||||
$focusedGrid
|
||||
)
|
||||
|
||||
@@ -12,11 +12,23 @@
|
||||
CheckboxComponent,
|
||||
SelectComponent
|
||||
} from '../apps/editor/component'
|
||||
export let actionsOrder: RichConfiguration | undefined = undefined
|
||||
export let selectedId: string | undefined = undefined
|
||||
export let components:
|
||||
| (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[]
|
||||
| undefined
|
||||
interface Props {
|
||||
actionsOrder?: RichConfiguration | undefined
|
||||
selectedId?: string | undefined
|
||||
components:
|
||||
| (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[]
|
||||
| undefined
|
||||
trigger?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
let {
|
||||
actionsOrder = $bindable(undefined),
|
||||
selectedId = undefined,
|
||||
components,
|
||||
trigger
|
||||
}: Props = $props()
|
||||
|
||||
const trigger_render = $derived(trigger)
|
||||
</script>
|
||||
|
||||
<Popover
|
||||
@@ -27,15 +39,15 @@
|
||||
}}
|
||||
closeButton
|
||||
>
|
||||
<svelte:fragment slot="trigger">
|
||||
<slot name="trigger" />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
{#snippet trigger()}
|
||||
{@render trigger_render?.()}
|
||||
{/snippet}
|
||||
{#snippet content()}
|
||||
<div class="w-96">
|
||||
<PanelSection
|
||||
title={`Manage actions programmatically`}
|
||||
tooltip="
|
||||
You can manage the order of the actions programmatically: You need to return an array of action ids in the order you want them to appear in the table. You can also hide actions by not including them in the array."
|
||||
You can manage the order of the actions programmatically: You need to return an array of action ids in the order you want them to appear in the table. You can also hide actions by not including them in the array."
|
||||
>
|
||||
<div class="w-full flex gap-2 flex-col mt-2">
|
||||
{#if actionsOrder}
|
||||
@@ -93,5 +105,5 @@
|
||||
</div>
|
||||
</PanelSection>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
|
||||
Reference in New Issue
Block a user