+
diff --git a/frontend/src/lib/components/apps/components/inputs/AppTextInput.svelte b/frontend/src/lib/components/apps/components/inputs/AppTextInput.svelte
index d36c8d5338..9bfa6f6463 100644
--- a/frontend/src/lib/components/apps/components/inputs/AppTextInput.svelte
+++ b/frontend/src/lib/components/apps/components/inputs/AppTextInput.svelte
@@ -2,10 +2,8 @@
import { getContext } from 'svelte'
import { twMerge } from 'tailwind-merge'
import { initOutput } from '../../editor/appUtils'
- import type { AppInput } from '../../inputType'
- import type { Output } from '../../rx'
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
- import { concatCustomCss } from '../../utils'
+ import { concatCustomCss, selectId } from '../../utils'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
@@ -46,12 +44,11 @@
{#if inputType === 'password'}
($selectedComponent = id)}
- on:pointerdown|stopPropagation={() => ($selectedComponent = id)}
+ on:pointerdown|stopPropagation={(e) => selectId(e, id, selectedComponent, $app)}
type="password"
bind:value
{placeholder}
@@ -59,12 +56,11 @@
{:else if inputType === 'text'}
($selectedComponent = id)}
- on:pointerdown|stopPropagation={() => ($selectedComponent = id)}
+ on:pointerdown|stopPropagation={(e) => selectId(e, id, selectedComponent, $app)}
type="text"
bind:value
{placeholder}
@@ -72,12 +68,11 @@
{:else if inputType === 'email'}
($selectedComponent = id)}
- on:pointerdown|stopPropagation={() => ($selectedComponent = id)}
+ on:pointerdown|stopPropagation={(e) => selectId(e, id, selectedComponent, $app)}
type="email"
bind:value
{placeholder}
diff --git a/frontend/src/lib/components/apps/components/inputs/currency/AppCurrencyInput.svelte b/frontend/src/lib/components/apps/components/inputs/currency/AppCurrencyInput.svelte
index 430dc6337b..576f8fcccf 100644
--- a/frontend/src/lib/components/apps/components/inputs/currency/AppCurrencyInput.svelte
+++ b/frontend/src/lib/components/apps/components/inputs/currency/AppCurrencyInput.svelte
@@ -54,7 +54,7 @@
{#key isNegativeAllowed}
{#key locale}
{#key currency}
-
($selectedComponent = id)}>
+
($selectedComponent = [id])}>
@@ -38,7 +38,7 @@
subGridId={`${id}-0`}
containerHeight={componentContainerHeight}
on:focus={() => {
- $selectedComponent = id
+ $selectedComponent = [id]
}}
/>
{/if}
diff --git a/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte b/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte
index 1a4763066e..7cf26b0c11 100644
--- a/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte
+++ b/frontend/src/lib/components/apps/components/layout/AppDrawer.svelte
@@ -47,7 +47,6 @@
{disabled}
on:pointerdown={(e) => {
e?.stopPropagation()
- window.dispatchEvent(new Event('pointerup'))
}}
on:click={async (e) => {
$focusedGrid = {
@@ -89,7 +88,7 @@
subGridId={`${id}-0`}
containerHeight={1200}
on:focus={() => {
- $selectedComponent = id
+ $selectedComponent = [id]
}}
/>
{/if}
diff --git a/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte b/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte
index 3454fbe3cc..0bfb9413ef 100644
--- a/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte
+++ b/frontend/src/lib/components/apps/components/layout/AppSplitpanes.svelte
@@ -29,7 +29,7 @@
}
}
- $: $selectedComponent === id && onFocus()
+ $: $selectedComponent?.includes(id) && onFocus()
$: css = concatCustomCss($app.css?.containercomponent, customCss)
$componentControl[id] = {
@@ -73,7 +73,7 @@
{
- $selectedComponent = id
+ $selectedComponent = [id]
$focusedGrid = {
parentComponentId: id,
subGridIndex: index
@@ -90,7 +90,7 @@
subGridId={`${id}-${index}`}
containerHeight={horizontal ? undefined : componentContainerHeight - 8}
on:focus={() => {
- $selectedComponent = id
+ $selectedComponent = [id]
$focusedGrid = {
parentComponentId: id,
subGridIndex: index
diff --git a/frontend/src/lib/components/apps/components/layout/AppTabs.svelte b/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
index 1fdb816d25..e7f34954fb 100644
--- a/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
+++ b/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
@@ -118,7 +118,7 @@
? componentContainerHeight - tabHeight
: componentContainerHeight}
on:focus={() => {
- $selectedComponent = id
+ $selectedComponent = [id]
}}
/>
{/each}
diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte
index 91a919b9fd..a9545c9982 100644
--- a/frontend/src/lib/components/apps/editor/AppEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte
@@ -51,7 +51,7 @@
export let fromHub: boolean = false
const appStore = writable
(app)
- const selectedComponent = writable(undefined)
+ const selectedComponent = writable(undefined)
const mode = writable(initialMode)
const breakpoint = writable('lg')
const summaryStore = writable(summary)
@@ -83,7 +83,7 @@
mode,
connectingInput,
breakpoint,
- runnableComponents,
+ runnableComponents: writable({}),
appPath: path,
workspace: $workspaceStore ?? '',
onchange: () => saveDraft(),
@@ -105,7 +105,7 @@
history,
pickVariableCallback,
ontextfocus: writable(undefined),
- movingcomponent: writable(undefined),
+ movingcomponents: writable(undefined),
selectedComponentInEditor: writable(undefined)
})
@@ -140,10 +140,10 @@
let selectedTab: 'insert' | 'settings' = 'insert'
- $: if ($selectedComponent) {
+ let befSelected: string | undefined = undefined
+ $: if ($selectedComponent?.[0] != befSelected) {
+ befSelected = $selectedComponent?.[0]
selectedTab = 'settings'
- } else {
- selectedTab = 'insert'
}
let itemPicker: ItemPicker | undefined = undefined
diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
index c0bfe301c8..d607184f28 100644
--- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
@@ -247,7 +247,17 @@
let lock = false
function onKeyDown(event: KeyboardEvent) {
if (lock) return
+
+ let classes = event.target?.['className']
+ if (
+ (typeof classes === 'string' && classes.includes('inputarea')) ||
+ ['INPUT', 'TEXTAREA'].includes(document.activeElement?.tagName!)
+ ) {
+ return
+ }
+
lock = true
+
switch (event.key) {
case 'Z':
if (event.ctrlKey) {
diff --git a/frontend/src/lib/components/apps/editor/AppPreview.svelte b/frontend/src/lib/components/apps/editor/AppPreview.svelte
index 31678700e2..44c5e2b810 100644
--- a/frontend/src/lib/components/apps/editor/AppPreview.svelte
+++ b/frontend/src/lib/components/apps/editor/AppPreview.svelte
@@ -33,7 +33,7 @@
export let isLocked = false
const appStore = writable(app)
- const selectedComponent = writable(undefined)
+ const selectedComponent = writable(undefined)
const mode = writable('preview')
const connectingInput = writable({
@@ -42,8 +42,6 @@
hoveredComponent: undefined
})
- const runnableComponents = writable Promise>>({})
-
const parentWidth = writable(0)
setContext('AppViewerContext', {
worldStore: buildWorld(context),
@@ -53,7 +51,7 @@
mode,
connectingInput,
breakpoint,
- runnableComponents,
+ runnableComponents: writable({}),
appPath,
workspace,
onchange: undefined,
@@ -118,7 +116,7 @@
>
($selectedComponent = dataItem.id)}
+ on:pointerdown={() => ($selectedComponent = [dataItem.id])}
>
@@ -159,6 +157,8 @@
inlineScript={script.inlineScript}
name={script.name}
fields={script.fields}
+ doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged ?? false}
+ recomputableByRefreshButton={script.autoRefresh ?? false}
/>
{/if}
{/each}
diff --git a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
index 57b42a26d8..de2afa991c 100644
--- a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
@@ -29,6 +29,7 @@
{#if selected || hover}
{
push(history, $app)
@@ -136,16 +136,16 @@
{/if}
selectComponent(dataItem.id)}
+ on:pointerdown={(e) => selectComponent(e, dataItem.id)}
class={classNames(
'h-full w-full center-center',
- $selectedComponent === dataItem.id ? 'active-grid-item' : ''
+ Boolean($selectedComponent?.includes(dataItem.id)) ? 'active-grid-item' : ''
)}
>
removeGridElement(dataItem.data)}
on:lock={() => {
@@ -157,7 +157,7 @@
}}
on:expand={() => {
push(history, $app)
- $selectedComponent = dataItem.id
+ $selectedComponent = [dataItem.id]
expandGriditem($app.grid, dataItem.id, $breakpoint)
$app = $app
}}
@@ -176,7 +176,8 @@
inlineScript={script.inlineScript}
name={script.name}
fields={script.fields}
- doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged}
+ doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged ?? false}
+ recomputableByRefreshButton={script.autoRefresh ?? false}
/>
{/if}
{/each}
diff --git a/frontend/src/lib/components/apps/editor/RecomputeAllComponents.svelte b/frontend/src/lib/components/apps/editor/RecomputeAllComponents.svelte
index c85216e761..1b50c3ab25 100644
--- a/frontend/src/lib/components/apps/editor/RecomputeAllComponents.svelte
+++ b/frontend/src/lib/components/apps/editor/RecomputeAllComponents.svelte
@@ -17,7 +17,7 @@
$worldStore.initializedOutputs ==
allItems($app.grid, $app.subgrids).length + $app.hiddenInlineScripts.length &&
refresh()
- $: componentNumber = Object.keys($runnableComponents).length
+ $: componentNumber = Object.values($runnableComponents).filter((x) => x.autoRefresh).length
function onClick(stopAfterClear = true) {
if (timeout) {
@@ -46,13 +46,10 @@
loading = true
Promise.all(
Object.keys($runnableComponents).map((id) => {
- if (id.startsWith('bg_')) {
- let index = parseInt(id.split('_')[1])
- if (!$app.hiddenInlineScripts[index]?.autoRefresh) {
- return
- }
+ if (!$runnableComponents?.[id]?.autoRefresh) {
+ return
}
- return $runnableComponents?.[id]?.()
+ return $runnableComponents?.[id]?.cb?.()
})
).finally(() => {
loading = false
@@ -82,6 +79,7 @@
diff --git a/frontend/src/lib/components/apps/editor/component/ComponentNavigation.svelte b/frontend/src/lib/components/apps/editor/component/ComponentNavigation.svelte
index af55b87a0c..66e5eaa6ad 100644
--- a/frontend/src/lib/components/apps/editor/component/ComponentNavigation.svelte
+++ b/frontend/src/lib/components/apps/editor/component/ComponentNavigation.svelte
@@ -14,10 +14,10 @@
const { app, selectedComponent, worldStore, focusedGrid, componentControl } =
getContext('AppViewerContext')
- const { history, movingcomponent } = getContext('AppEditorContext')
+ const { history, movingcomponents } = getContext('AppEditorContext')
- let tempGridItem: GridItem | undefined = undefined
- let copiedGridItem: GridItem | undefined = undefined
+ let tempGridItems: GridItem[] | undefined = undefined
+ let copiedGridItems: GridItem[] | undefined = undefined
function getSortedGridItemsOfChildren(): GridItem[] {
if (!$focusedGrid) {
@@ -32,7 +32,7 @@
}
function getGridItems(): GridItem[] {
- if ($app.grid.find((item) => item.id === $selectedComponent)) {
+ if ($app.grid.find((item) => item.id === $selectedComponent?.[0])) {
return $app.grid
}
@@ -42,23 +42,25 @@
return (
Object.values($app.subgrids ?? {}).find((grid) =>
- grid.find((item) => item.id === $selectedComponent)
+ grid.find((item) => item.id === $selectedComponent?.[0])
) ?? []
)
}
function left(event: KeyboardEvent) {
- if (!$componentControl[$selectedComponent!]?.left?.()) {
+ if (!$componentControl[$selectedComponent?.[0] ?? '']?.left?.()) {
const sortedGridItems = getGridItems()
- const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
+ const currentIndex = sortedGridItems.findIndex(
+ (item) => item.id === $selectedComponent?.[0] ?? ''
+ )
if (currentIndex !== -1 && currentIndex > 0) {
const left = sortedGridItems[currentIndex - 1]
if (left.data.type === 'tablecomponent' && left.data.actionButtons.length >= 1) {
- $selectedComponent = left.data.actionButtons[left.data.actionButtons.length - 1].id
+ $selectedComponent = [left.data.actionButtons[left.data.actionButtons.length - 1].id]
} else {
- $selectedComponent = left.id
+ $selectedComponent = [left.id]
}
}
}
@@ -67,19 +69,21 @@
}
function right(event: KeyboardEvent) {
- let r = $componentControl[$selectedComponent!]?.right?.()
+ let r = $componentControl[$selectedComponent?.[0] ?? '']?.right?.()
if (typeof r === 'string') {
- $selectedComponent = r
+ $selectedComponent = [r]
r = $componentControl[r]?.right?.(true)
}
if (!r) {
const sortedGridItems = getGridItems()
- const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
+ const currentIndex = sortedGridItems.findIndex(
+ (item) => item.id === $selectedComponent?.[0] ?? ''
+ )
if (currentIndex !== -1 && currentIndex < sortedGridItems.length - 1) {
- $selectedComponent = sortedGridItems[currentIndex + 1].id
+ $selectedComponent = [sortedGridItems[currentIndex + 1].id]
}
}
@@ -88,7 +92,7 @@
function down(event: KeyboardEvent) {
if (!$focusedGrid) {
- $selectedComponent = getSortedGridItemsOfChildren()[0]?.id
+ $selectedComponent = [getSortedGridItemsOfChildren()[0]?.id]
event.preventDefault()
} else if ($app.subgrids) {
const index = $focusedGrid?.subGridIndex ?? 0
@@ -99,7 +103,7 @@
}
if (subgrid) {
- $selectedComponent = subgrid[0].id
+ $selectedComponent = [subgrid[0].id]
}
event.preventDefault()
}
@@ -113,10 +117,10 @@
function handleArrowUp(event: KeyboardEvent) {
if (!$selectedComponent) return
- let parentId = findGridItemParentGrid($app, $selectedComponent)?.split('-')[0]
+ let parentId = findGridItemParentGrid($app, $selectedComponent?.[0])?.split('-')[0]
if (parentId) {
- $selectedComponent = parentId
+ $selectedComponent = [parentId]
} else {
$selectedComponent = undefined
$focusedGrid = undefined
@@ -127,72 +131,82 @@
if (!$selectedComponent) {
return
}
- tempGridItem = undefined
- copiedGridItem = findGridItem($app, $selectedComponent)
+ tempGridItems = undefined
+ copiedGridItems = $selectedComponent
+ .map((x) => findGridItem($app, x))
+ .filter((x) => x != undefined) as GridItem[]
}
function handleCut(event: KeyboardEvent) {
if (!$selectedComponent) {
return
}
- $movingcomponent = $selectedComponent
+ $movingcomponents = JSON.parse(JSON.stringify($selectedComponent))
push(history, $app)
- const gridItem = findGridItem($app, $selectedComponent)
- copiedGridItem = gridItem
+ let gridItems = $selectedComponent
+ .map((x) => findGridItem($app, x))
+ .filter((x) => x != undefined) as GridItem[]
+ copiedGridItems = gridItems
- if (!gridItem) {
+ if (!gridItems) {
return
}
// Store the grid item in a temp variable so we can paste it later
- tempGridItem = gridItem
+ tempGridItems = gridItems
}
function handlePaste(event: KeyboardEvent) {
push(history, $app)
- $movingcomponent = undefined
- if (tempGridItem != undefined) {
- if (
- $focusedGrid &&
- getAllSubgridsAndComponentIds($app, tempGridItem.data)[0].includes(
- `${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`
+ $movingcomponents = undefined
+ if (tempGridItems != undefined) {
+ for (let tempGridItem of tempGridItems) {
+ if (
+ $focusedGrid &&
+ getAllSubgridsAndComponentIds($app, tempGridItem.data)[0].includes(
+ `${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`
+ )
+ ) {
+ sendUserToast('Cannot paste a component into itself', true)
+ return
+ }
+ let parentGrid = findGridItemParentGrid($app, tempGridItem.id)
+ if (parentGrid) {
+ $app.subgrids &&
+ ($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter(
+ (item) => item.id !== tempGridItem?.id
+ ))
+ } else {
+ $app.grid = $app.grid.filter((item) => item.id !== tempGridItem?.id)
+ }
+
+ const gridItem = tempGridItem
+ insertNewGridItem(
+ $app,
+ (id) => ({ ...gridItem.data, id }),
+ $focusedGrid,
+ Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])),
+ tempGridItem.id
)
- ) {
- sendUserToast('Cannot paste a component into itself', true)
- return
}
- let parentGrid = findGridItemParentGrid($app, tempGridItem.id)
- if (parentGrid) {
- $app.subgrids &&
- ($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter(
- (item) => item.id !== tempGridItem?.id
- ))
- } else {
- $app.grid = $app.grid.filter((item) => item.id !== tempGridItem?.id)
+ copiedGridItems = tempGridItems
+ $selectedComponent = tempGridItems.map((x) => x.id)
+
+ tempGridItems = undefined
+ } else if (copiedGridItems) {
+ let nitems: string[] = []
+ for (let copiedGridItem of copiedGridItems) {
+ nitems.push(
+ insertNewGridItem(
+ $app,
+ (id) => ({ ...copiedGridItem.data, id }),
+ $focusedGrid,
+ Object.fromEntries(gridColumns.map((column) => [column, copiedGridItem[column]]))
+ )
+ )
}
-
- const gridItem = tempGridItem
- insertNewGridItem(
- $app,
- (id) => ({ ...gridItem.data, id }),
- $focusedGrid,
- Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])),
- tempGridItem.id
- )
-
- copiedGridItem = tempGridItem
- $selectedComponent = tempGridItem.id
-
- tempGridItem = undefined
- } else if (copiedGridItem) {
- const gridItem = copiedGridItem
- $selectedComponent = insertNewGridItem(
- $app,
- (id) => ({ ...gridItem.data, id }),
- $focusedGrid,
- Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]]))
- )
+ $selectedComponent = nitems.map((x) => x)
}
$worldStore = $worldStore
diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte
index 21481f54ae..9436cad007 100644
--- a/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte
+++ b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte
@@ -31,7 +31,7 @@
$focusedGrid
)
- $selectedComponent = id
+ $selectedComponent = [id]
$app = $app
$worldStore = $worldStore
}
diff --git a/frontend/src/lib/components/apps/editor/contextPanel/ComponentOutput.svelte b/frontend/src/lib/components/apps/editor/contextPanel/ComponentOutput.svelte
index 48e68e0df2..3c72e54fe7 100644
--- a/frontend/src/lib/components/apps/editor/contextPanel/ComponentOutput.svelte
+++ b/frontend/src/lib/components/apps/editor/contextPanel/ComponentOutput.svelte
@@ -36,12 +36,12 @@
function onHeaderClick(manuallyOpen: boolean) {
if (manuallyOpen) {
if (parentId) {
- $selectedComponent = parentId
+ $selectedComponent = [parentId]
} else {
$selectedComponent = undefined
}
} else {
- $selectedComponent = gridItem.id
+ $selectedComponent = [gridItem.id]
}
}
diff --git a/frontend/src/lib/components/apps/editor/contextPanel/components/BackgroundScriptOutput.svelte b/frontend/src/lib/components/apps/editor/contextPanel/components/BackgroundScriptOutput.svelte
index 8be9838d4b..79754c78b5 100644
--- a/frontend/src/lib/components/apps/editor/contextPanel/components/BackgroundScriptOutput.svelte
+++ b/frontend/src/lib/components/apps/editor/contextPanel/components/BackgroundScriptOutput.svelte
@@ -14,12 +14,12 @@
function onHeaderClick(manuallyOpen: boolean) {
if (manuallyOpen) {
if (id) {
- $selectedComponent = id
+ $selectedComponent = [id]
} else {
$selectedComponent = undefined
}
} else {
- $selectedComponent = id
+ $selectedComponent = [id]
}
}
diff --git a/frontend/src/lib/components/apps/editor/contextPanel/components/OutputHeader.svelte b/frontend/src/lib/components/apps/editor/contextPanel/components/OutputHeader.svelte
index 5e35e05767..31f8a60926 100644
--- a/frontend/src/lib/components/apps/editor/contextPanel/components/OutputHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/contextPanel/components/OutputHeader.svelte
@@ -22,7 +22,10 @@
($hasResult[id] ||
Object.entries($hasResult).some(([key, value]) => value && subids.includes(key)))
$: open =
- $expanded || subids.includes($selectedComponent ?? '') || $manuallyOpened[id] || inSearch
+ $expanded ||
+ subids.some((x) => $selectedComponent?.includes(x)) ||
+ $manuallyOpened[id] ||
+ inSearch
const dispatch = createEventDispatcher()
@@ -64,7 +67,7 @@
class={classNames(
'flex items-center justify-between p-1 cursor-pointer border-b gap-1 truncate',
hoverColor[color],
- $selectedComponent == id ? openBackground[color] : 'bg-white',
+ $selectedComponent?.includes(id) ? openBackground[color] : 'bg-white',
first ? 'border-t' : '',
nested ? 'border-l' : ''
)}
@@ -76,7 +79,7 @@
{id}
diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte
index a710762c6c..de8de910e5 100644
--- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte
@@ -191,7 +191,7 @@
btnClasses="!px-2 !py-1 !bg-gray-700 !text-white hover:!bg-gray-900"
on:click={async () => {
runLoading = true
- await $runnableComponents[id]?.(!transformer ? inlineScript : undefined)
+ await $runnableComponents[id]?.cb?.(!transformer ? inlineScript : undefined)
runLoading = false
}}
>
@@ -227,7 +227,7 @@
inlineScript.content = editor?.getCode() ?? ''
}
runLoading = true
- await $runnableComponents[id]?.(inlineScript)
+ await $runnableComponents[id]?.cb?.(inlineScript)
runLoading = false
}}
on:change={async (e) => {
@@ -250,7 +250,7 @@
bind:this={simpleEditor}
cmdEnterAction={async () => {
runLoading = true
- await $runnableComponents[id]?.(!transformer ? inlineScript : undefined)
+ await $runnableComponents[id]?.cb?.(!transformer ? inlineScript : undefined)
runLoading = false
}}
class="h-full"
diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte
index e71b8d8a96..6b0808fe2a 100644
--- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte
+++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte
@@ -16,7 +16,7 @@
function selectScript(id: string) {
$selectedComponentInEditor = id
if (!id.startsWith('unused-') || !id.startsWith('bg_')) {
- $selectedComponent = $selectedComponentInEditor.split('_transformer')[0]
+ $selectedComponent = [$selectedComponentInEditor.split('_transformer')[0]]
}
}
@@ -27,7 +27,7 @@
$selectedComponent != $selectedComponentInEditor &&
!$selectedComponentInEditor?.includes('_transformer')
) {
- $selectedComponentInEditor = $selectedComponent
+ $selectedComponentInEditor = $selectedComponent?.[0]
}
function createBackgroundScript() {
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
index 5211c90017..999d1728ef 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
@@ -300,6 +300,10 @@
↑→
ESC
+
+ Add to selection:
+ ⇑+click
+
{/if}
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte
index 2ab3621006..0c64a5701d 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte
@@ -39,7 +39,7 @@
$errorByComponent = clearErrorByComponentId(cid, $errorByComponent)
$jobs = clearJobsByComponentId(cid, $jobs)
- $selectedComponent = id
+ $selectedComponent = [id]
$app = $app
}
@@ -64,10 +64,10 @@
class={classNames(
'w-full text-xs font-bold gap-1 truncate py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
'bg-white border-gray-300 hover:bg-gray-100 focus:bg-gray-100 text-gray-700',
- $selectedComponent === component.id ? 'outline outline-blue-500 bg-red-400' : ''
+ $selectedComponent?.includes(component.id) ? 'outline outline-blue-500 bg-red-400' : ''
)}
on:click={() => {
- $selectedComponent = component.id
+ $selectedComponent = [component.id]
}}
on:keypress
>
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/triggerLists/ComponentTriggerList.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/triggerLists/ComponentTriggerList.svelte
index c43fd73437..0fa69d7e22 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/triggerLists/ComponentTriggerList.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/triggerLists/ComponentTriggerList.svelte
@@ -34,6 +34,6 @@
bind:inlineScript={runnable.inlineScript}
{onLoad}
{doNotRecomputeOnInputChanged}
- id={$selectedComponent}
+ id={$selectedComponent?.[0]}
{onClick}
/>
diff --git a/frontend/src/lib/components/apps/svelte-grid/Grid.svelte b/frontend/src/lib/components/apps/svelte-grid/Grid.svelte
index fde8289f98..fc4181b74a 100644
--- a/frontend/src/lib/components/apps/svelte-grid/Grid.svelte
+++ b/frontend/src/lib/components/apps/svelte-grid/Grid.svelte
@@ -18,7 +18,7 @@
export let fastStart = false
export let throttleUpdate = 100
export let throttleResize = 100
- export let onTopId: string | undefined = undefined
+ export let selectedIds: string[] | undefined
export let containerWidth: number | undefined = undefined
export let scroller: HTMLElement | undefined = undefined
@@ -37,13 +37,6 @@
$: containerHeight = getContainerHeight(items, yPerPx, getComputedCols)
- const pointerup = (ev) => {
- dispatch('pointerup', {
- id: ev.detail.id,
- cols: getComputedCols
- })
- }
-
const onResize = throttle(() => {
items = specifyUndefinedColumns(items, getComputedCols, cols)
dispatch('resize', {
@@ -91,6 +84,7 @@
let initItems: FilledItem[] | undefined = undefined
const updateMatrix = ({ detail }) => {
+ console.log('updateMatrix', detail)
let isPointerUp = detail.isPointerUp
let citems: FilledItem[]
if (isPointerUp) {
@@ -107,26 +101,32 @@
citems = JSON.parse(JSON.stringify(initItems))
}
- let activeItem = getItemById(detail.id, citems)
+ sortedItems = citems
+ for (let id of selectedIds ?? []) {
+ let activeItem = getItemById(id, sortedItems)
- if (activeItem) {
- activeItem = {
- ...activeItem,
- [getComputedCols]: {
- ...activeItem[getComputedCols],
- ...detail.shadow
+ if (activeItem) {
+ activeItem = {
+ ...activeItem,
+ [getComputedCols]: {
+ ...activeItem[getComputedCols],
+ ...shadows[id]
+ }
}
+
+ sortedItems = moveItem(
+ activeItem,
+ sortedItems,
+ getComputedCols,
+ getItemById(id, sortedItems)
+ )
}
+ }
- sortedItems = moveItem(activeItem, citems, getComputedCols, getItemById(detail.id, citems))
-
- if (detail.onUpdate) detail.onUpdate()
-
- dispatch('change', {
- unsafeItem: activeItem,
- id: activeItem.id,
- cols: getComputedCols
- })
+ for (let id of selectedIds ?? []) {
+ if (detail.activate) {
+ moveResizes?.[id]?.inActivate()
+ }
}
if (isPointerUp) {
@@ -146,15 +146,37 @@
updateMatrix({ detail })
}
}
+ let moveResizes: Record = {}
+ let shadows: Record = {}
+
+ export function handleMove({ detail }) {
+ Object.entries(moveResizes).forEach(([id, moveResize]) => {
+ if (selectedIds?.includes(id)) {
+ moveResize?.updateMove(JSON.parse(JSON.stringify(detail.cordDiff)), detail.eventY)
+ }
+ })
+ throttleMatrix({ detail: { isPointerUp: false, activate: false } })
+ }
+
+ export function handleInitMove({ detail }) {
+ Object.entries(moveResizes).forEach(([id, moveResize]) => {
+ if (selectedIds?.includes(id)) {
+ moveResize?.initmove()
+ }
+ })
+ }
{#if xPerPx || !fastStart}
{#each sortedItems as item (item.id)}
diff --git a/frontend/src/lib/components/apps/svelte-grid/MoveResize.svelte b/frontend/src/lib/components/apps/svelte-grid/MoveResize.svelte
index a398d2dfd5..33fcd39cc1 100644
--- a/frontend/src/lib/components/apps/svelte-grid/MoveResize.svelte
+++ b/frontend/src/lib/components/apps/svelte-grid/MoveResize.svelte
@@ -23,9 +23,10 @@
export let nativeContainer
export let onTop
+ export let shadow: { x: number; y: number; w: number; h: number } | undefined = undefined
+ const divId = `component-${id}`
let shadowElement
- let shadow: { x: number; y: number; w: number; h: number } | undefined = undefined
let active = false
@@ -43,7 +44,7 @@
let anima
- const inActivate = () => {
+ export function inActivate() {
if (shadowElement && shadow != undefined) {
let subgrid = shadowElement.closest('.subgrid')
let irect = shadowElement.getBoundingClientRect()
@@ -80,20 +81,14 @@
anima = setTimeout(() => {
trans = false
- }, 100)
-
- dispatch('pointerup', {
- id
- })
+ }, 50)
}
}
- let repaint = (cb: (() => void) | undefined, isPointerUp: boolean) => {
+ let repaint = (activate: boolean, isPointerUp: boolean) => {
dispatch('repaint', {
- id,
- shadow,
isPointerUp,
- onUpdate: cb
+ activate
})
}
@@ -105,7 +100,7 @@
const getContainerFrame = (element) => {
if (element === document.documentElement || !element) {
- const { height, top, right, bottom, left } = nativeContainer.getBoundingClientRect()
+ const { top, bottom } = nativeContainer.getBoundingClientRect()
return {
top: Math.max(0, top),
@@ -118,12 +113,13 @@
const getScroller = (element) => (!element ? document.documentElement : element)
- function computeRect(target) {
- let gridItem = target.closest('.svlt-grid-item')
+ function computeRect() {
+ let gridItem = document.getElementById(divId)
+ if (!gridItem) return
let subgrid = gridItem.closest('.subgrid')
let irect = gridItem.getBoundingClientRect()
- if (subgrid) {
+ if (subgrid && subgrid.parentElement) {
let subGridParent = subgrid.parentElement
let subGridParentRect = subGridParent.getBoundingClientRect()
@@ -150,25 +146,27 @@
initX = clientX
initY = clientY
-
- capturePos = { x: left, y: top }
- shadow = { x: item.x, y: item.y, w: item.w, h: item.h }
- newSize = { width, height }
-
- containerFrame = getContainerFrame(container)
- scrollElement = getScroller(container)
-
- cordDiff = { x: 0, y: 0 }
-
- active = true
- trans = false
- computeRect(target)
- _scrollTop = scrollElement.scrollTop
+ dispatch('initmove')
}
window.addEventListener('pointermove', pointermove)
window.addEventListener('pointerup', pointerup)
}
+ export function initmove() {
+ computeRect()
+ newSize = { width, height }
+ capturePos = { x: left, y: top }
+ shadow = { x: item.x, y: item.y, w: item.w, h: item.h }
+ cordDiff = { x: 0, y: 0 }
+ active = true
+ trans = false
+
+ containerFrame = getContainerFrame(container)
+ scrollElement = getScroller(container)
+
+ _scrollTop = scrollElement.scrollTop
+ }
+
let sign = { x: 0, y: 0 }
let vel = { x: 0, y: 0 }
let intervalId: NodeJS.Timer | undefined = undefined
@@ -181,9 +179,8 @@
}
const update = () => {
- const _newScrollTop = scrollElement.scrollTop - _scrollTop
-
const boundX = capturePos.x + cordDiff.x
+ const _newScrollTop = (scrollElement?.scrollTop ?? 0) - (_scrollTop ?? 0)
const boundY = capturePos.y + (cordDiff.y + _newScrollTop)
let gridX = Math.round(boundX / xPerPx)
@@ -193,7 +190,6 @@
shadow.x = Math.max(Math.min(gridX, cols - shadow.w), 0)
shadow.y = Math.max(gridY, 0)
}
- repaint(undefined, false)
}
const pointermove = (event) => {
@@ -203,60 +199,76 @@
event.stopImmediatePropagation()
const { clientX, clientY } = event
- cordDiff = { x: clientX - initX, y: clientY - initY }
+ const cordDiff = { x: clientX - initX, y: clientY - initY }
+ dispatch('move', { cordDiff, clientY })
+ }
+
+ export function updateMove(newCoordDiff, clientY) {
+ if (!active) {
+ active = true
+ }
+ if (trans) {
+ trans = false
+ }
+ cordDiff = newCoordDiff
+ // console.log(cordDiff, id, 'B')
const Y_SENSOR = sensor
- let velocityTop = Math.max(0, (containerFrame.top + Y_SENSOR - clientY) / Y_SENSOR)
- let velocityBottom = Math.max(0, (clientY - (containerFrame.bottom - Y_SENSOR)) / Y_SENSOR)
+ if (containerFrame) {
+ let velocityTop = Math.max(0, (containerFrame.top + Y_SENSOR - clientY) / Y_SENSOR)
+ let velocityBottom = Math.max(0, (clientY - (containerFrame.bottom - Y_SENSOR)) / Y_SENSOR)
- const topSensor = velocityTop > 0 && velocityBottom === 0
- const bottomSensor = velocityBottom > 0 && velocityTop === 0
+ const topSensor = velocityTop > 0 && velocityBottom === 0
+ const bottomSensor = velocityBottom > 0 && velocityTop === 0
- sign.y = topSensor ? -1 : bottomSensor ? 1 : 0
- vel.y = sign.y === -1 ? velocityTop : velocityBottom
+ sign.y = topSensor ? -1 : bottomSensor ? 1 : 0
+ vel.y = sign.y === -1 ? velocityTop : velocityBottom
- if (vel.y > 0) {
- if (!intervalId) {
- // Start scrolling
- // TODO Use requestAnimationFrame
- intervalId = setInterval(() => {
- scrollElement.scrollTop += 2 * (vel.y + Math.sign(vel.y)) * sign.y
- update()
- }, 10)
+ if (vel.y > 0) {
+ if (!intervalId) {
+ // Start scrolling
+ // TODO Use requestAnimationFrame
+ intervalId = setInterval(() => {
+ scrollElement.scrollTop += 2 * (vel.y + Math.sign(vel.y)) * sign.y
+ update()
+ }, 10)
+ }
+ } else if (intervalId) {
+ stopAutoscroll()
+ } else {
+ update()
}
- } else if (intervalId) {
- stopAutoscroll()
} else {
update()
}
}
-
const pointerup = (e) => {
- dragClosure = undefined
stopAutoscroll()
window.removeEventListener('pointerdown', pointerdown)
window.removeEventListener('pointermove', pointermove)
window.removeEventListener('pointerup', pointerup)
- repaint(inActivate, true)
+ if (!dragClosure) {
+ repaint(true, true)
+ } else {
+ dragClosure = undefined
+ }
}
- // Resize
-
let resizeInitPos = { x: 0, y: 0 }
let initSize = { width: 0, height: 0 }
const resizePointerDown = (e) => {
e.stopPropagation()
- const { pageX, pageY, target } = e
+ const { pageX, pageY } = e
resizeInitPos = { x: pageX, y: pageY }
initSize = { width, height }
cordDiff = { x: 0, y: 0 }
- computeRect(target)
+ computeRect()
newSize = { width, height }
@@ -287,14 +299,14 @@
shadow.w = Math.round((newSize.width + gapX * 2) / xPerPx)
shadow.h = Math.round((newSize.height + gapY * 2) / yPerPx)
- repaint(undefined, false)
+ repaint(false, false)
}
}
const resizePointerUp = (e) => {
e.stopPropagation()
- repaint(inActivate, true)
+ repaint(true, true)
window.removeEventListener('pointermove', resizePointerMove)
window.removeEventListener('pointerup', resizePointerUp)
@@ -305,12 +317,13 @@
-
- {#if user}
- Logged in as {user.email}
- {:else}
- Not logged in
- {/if}
-
-
Go to app
-
+
{#if notExists}