mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-26 00:01:37 +00:00
fix key navigation
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import type { Output } from '../../rx'
|
||||
|
||||
export let id: string
|
||||
export let configuration: Record<string, AppInput>
|
||||
@@ -17,9 +16,7 @@
|
||||
export let panes: number[]
|
||||
export let render: boolean
|
||||
|
||||
export const staticOutputs: string[] = ['selectedTabIndex']
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore } =
|
||||
const { app, focusedGrid, selectedComponent, componentControl } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let noPadding: boolean | undefined = undefined
|
||||
@@ -31,23 +28,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
selectedTabIndex: Output<number | null>
|
||||
}
|
||||
|
||||
$: $selectedComponent === id && onFocus()
|
||||
$: css = concatCustomCss($app.css?.containercomponent, customCss)
|
||||
|
||||
$: outputs?.selectedTabIndex.subscribe({
|
||||
next: (value) => {
|
||||
if (value !== null) {
|
||||
$focusedGrid = {
|
||||
parentComponentId: id,
|
||||
subGridIndex: value
|
||||
$componentControl[id] = {
|
||||
left: () => {
|
||||
if ($focusedGrid?.subGridIndex) {
|
||||
const index = $focusedGrid?.subGridIndex ?? 0
|
||||
if (index > 0) {
|
||||
$focusedGrid.subGridIndex = index - 1
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
right: () => {
|
||||
if ($focusedGrid?.subGridIndex) {
|
||||
const index = $focusedGrid?.subGridIndex ?? 0
|
||||
if (index < panes.length - 1) {
|
||||
$focusedGrid.subGridIndex = index - 1
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let sumedup = [50, 50]
|
||||
$: {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
export let render: boolean
|
||||
|
||||
export const staticOutputs: string[] = ['selectedTabIndex']
|
||||
const { app, worldStore, focusedGrid, selectedComponent } =
|
||||
const { app, worldStore, focusedGrid, selectedComponent, componentControl } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let selected: string = tabs[0]
|
||||
@@ -41,22 +41,45 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: selected && outputs?.selectedTabIndex && handleTabSelection()
|
||||
$: $selectedComponent === id && focusGrid()
|
||||
|
||||
function focusGrid() {
|
||||
const selectedIndex = tabs?.indexOf(selected)
|
||||
if ($focusedGrid?.parentComponentId != id || $focusedGrid?.subGridIndex != selectedIndex) {
|
||||
$focusedGrid = {
|
||||
parentComponentId: id,
|
||||
subGridIndex: selectedIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$componentControl[id] = {
|
||||
left: () => {
|
||||
const index = tabs.indexOf(selected)
|
||||
if (index > 0) {
|
||||
selected = tabs[index - 1]
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
right: () => {
|
||||
const index = tabs.indexOf(selected)
|
||||
if (index < tabs.length - 1) {
|
||||
selected = tabs[index + 1]
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
$: selected && handleTabSelection()
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
selectedTabIndex: Output<number | null>
|
||||
}
|
||||
|
||||
$: selectedIndex = tabs?.indexOf(selected) ?? -1
|
||||
|
||||
$: outputs?.selectedTabIndex.subscribe({
|
||||
next: (value) => {
|
||||
if (selectedIndex !== value && value !== null) {
|
||||
selectedIndex = value
|
||||
selected = tabs[selectedIndex]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$: css = concatCustomCss($app.css?.tabscomponent, customCss)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
focusedGrid,
|
||||
stateId: writable(0),
|
||||
parentWidth: writable(0),
|
||||
history
|
||||
history,
|
||||
componentControl: writable({})
|
||||
})
|
||||
|
||||
let timeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
focusedGrid: writable(undefined),
|
||||
stateId: writable(0),
|
||||
parentWidth: writable(0),
|
||||
history: writable<any>(undefined)
|
||||
history: writable<any>(undefined),
|
||||
componentControl: writable({})
|
||||
})
|
||||
|
||||
let mounted = false
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, EditorBreakpoint, GridItem } from '../../types'
|
||||
import { findGridItem, findGridItemParentId } from '../appUtils'
|
||||
import { findGridItemParentId } from '../appUtils'
|
||||
|
||||
const { app, selectedComponent, breakpoint, worldStore } =
|
||||
const { app, selectedComponent, breakpoint, componentControl, focusedGrid } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
$: outputs = $selectedComponent ? $worldStore?.outputsById[$selectedComponent] : undefined
|
||||
|
||||
function getSortedGridItems(parentId: string | undefined): GridItem[] {
|
||||
if (!parentId) {
|
||||
function getSortedGridItemsOfChildren(): GridItem[] {
|
||||
if (!$focusedGrid) {
|
||||
return sortGridItems($app.grid, $breakpoint)
|
||||
}
|
||||
|
||||
@@ -17,97 +15,109 @@
|
||||
return []
|
||||
}
|
||||
|
||||
const index = getSubIndex(parentId)
|
||||
|
||||
return sortGridItems($app.subgrids[`${parentId}-${index}`], $breakpoint)
|
||||
return sortGridItems(
|
||||
$app.subgrids[`${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`],
|
||||
$breakpoint
|
||||
)
|
||||
}
|
||||
|
||||
function getSubIndex(id: string | undefined): number {
|
||||
if (!id) {
|
||||
return 0
|
||||
function getSortedGridItemsOfGrid(): GridItem[] {
|
||||
if ($app.grid.find((item) => item.id === $selectedComponent)) {
|
||||
return sortGridItems($app.grid, $breakpoint)
|
||||
}
|
||||
|
||||
const outputs = $worldStore?.outputsById[id]
|
||||
|
||||
let index = outputs?.selectedTabIndex ? outputs.selectedTabIndex.peak() : 0
|
||||
if (index === undefined) {
|
||||
index = 0
|
||||
if (!$app.subgrids) {
|
||||
return []
|
||||
}
|
||||
|
||||
return index
|
||||
return sortGridItems(
|
||||
Object.values($app.subgrids ?? {}).find((grid) =>
|
||||
grid.find((item) => item.id === $selectedComponent)
|
||||
) ?? [],
|
||||
$breakpoint
|
||||
)
|
||||
}
|
||||
|
||||
function left(event) {
|
||||
if (!$componentControl[$selectedComponent!]?.left?.()) {
|
||||
const sortedGridItems = getSortedGridItemsOfGrid()
|
||||
const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
|
||||
|
||||
if (currentIndex !== -1 && currentIndex > 0) {
|
||||
$selectedComponent = sortedGridItems[currentIndex - 1].id
|
||||
}
|
||||
event.preventDefault()
|
||||
} else {
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
function right(event) {
|
||||
let r = $componentControl[$selectedComponent!]?.right?.()
|
||||
if (!r) {
|
||||
const sortedGridItems = getSortedGridItemsOfGrid()
|
||||
const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
|
||||
|
||||
if (currentIndex !== -1 && currentIndex < sortedGridItems.length - 1) {
|
||||
$selectedComponent = sortedGridItems[currentIndex + 1].id
|
||||
}
|
||||
event.preventDefault()
|
||||
} else {
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
function down(event) {
|
||||
if (!$focusedGrid) {
|
||||
$selectedComponent = getSortedGridItemsOfChildren()[0]?.id
|
||||
} else if ($app.subgrids) {
|
||||
const index = $focusedGrid?.subGridIndex ?? 0
|
||||
const subgrid = $app.subgrids[`${$selectedComponent}-${index}`]
|
||||
|
||||
if (!subgrid || subgrid.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const sortedGridItems = sortGridItems(subgrid, $breakpoint)
|
||||
|
||||
if (sortedGridItems) {
|
||||
$selectedComponent = sortedGridItems[0].id
|
||||
}
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
if (!$selectedComponent) {
|
||||
return
|
||||
}
|
||||
|
||||
const parentId = findGridItemParentId($app, $selectedComponent)
|
||||
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
$selectedComponent = undefined
|
||||
event.preventDefault()
|
||||
break
|
||||
|
||||
case 'ArrowUp': {
|
||||
if (!$selectedComponent) return
|
||||
let parentId = findGridItemParentId($app, $selectedComponent)
|
||||
if (parentId) {
|
||||
$selectedComponent = parentId
|
||||
} else {
|
||||
$selectedComponent = undefined
|
||||
$focusedGrid = undefined
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'ArrowDown': {
|
||||
if ($app.subgrids) {
|
||||
const index = getSubIndex($selectedComponent)
|
||||
const subgrid = $app.subgrids[`${$selectedComponent}-${index}`]
|
||||
|
||||
if (!subgrid || subgrid.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const sortedGridItems = sortGridItems(subgrid, $breakpoint)
|
||||
|
||||
if (sortedGridItems) {
|
||||
$selectedComponent = sortedGridItems[0].id
|
||||
}
|
||||
}
|
||||
down(event)
|
||||
break
|
||||
}
|
||||
|
||||
case 'ArrowRight': {
|
||||
const index = getSubIndex($selectedComponent)
|
||||
const gridItem = findGridItem($app, $selectedComponent)
|
||||
|
||||
if (index < gridItem?.data.numberOfSubgrids - 1) {
|
||||
outputs?.selectedTabIndex?.set(index + 1)
|
||||
} else {
|
||||
const sortedGridItems = getSortedGridItems(parentId)
|
||||
const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
|
||||
|
||||
if (currentIndex !== -1 && currentIndex < sortedGridItems.length - 1) {
|
||||
$selectedComponent = sortedGridItems[currentIndex + 1].id
|
||||
}
|
||||
}
|
||||
|
||||
right(event)
|
||||
break
|
||||
}
|
||||
|
||||
case 'ArrowLeft': {
|
||||
const index = getSubIndex($selectedComponent)
|
||||
|
||||
if (index > 0) {
|
||||
outputs?.selectedTabIndex?.set(index - 1)
|
||||
} else {
|
||||
const sortedGridItems = getSortedGridItems(parentId)
|
||||
const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent)
|
||||
|
||||
if (currentIndex !== -1 && currentIndex > 0) {
|
||||
$selectedComponent = sortedGridItems[currentIndex - 1].id
|
||||
}
|
||||
}
|
||||
|
||||
left(event)
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
export let tabs: string[]
|
||||
export let component: AppComponent
|
||||
|
||||
const { app, staticOutputs, runnableComponents } =
|
||||
const { app, staticOutputs, runnableComponents, focusedGrid } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
function addTab() {
|
||||
|
||||
@@ -43,14 +43,14 @@ export interface BaseAppComponent extends Partial<Aligned> {
|
||||
configuration: Record<
|
||||
string,
|
||||
GeneralAppInput &
|
||||
(
|
||||
| StaticAppInput
|
||||
| ConnectedAppInput
|
||||
| UserAppInput
|
||||
| RowAppInput
|
||||
| EvalAppInput
|
||||
| UploadAppInput
|
||||
)
|
||||
(
|
||||
| StaticAppInput
|
||||
| ConnectedAppInput
|
||||
| UserAppInput
|
||||
| RowAppInput
|
||||
| EvalAppInput
|
||||
| UploadAppInput
|
||||
)
|
||||
>
|
||||
card: boolean | undefined
|
||||
customCss?: ComponentCustomCSS
|
||||
@@ -134,6 +134,7 @@ export type AppEditorContext = {
|
||||
stateId: Writable<number>
|
||||
parentWidth: Writable<number>
|
||||
history: History<App>
|
||||
componentControl: Writable<Record<string, { left?: () => boolean; right?: () => boolean }>>
|
||||
}
|
||||
|
||||
export type FocusedGrid = { parentComponentId: string; subGridIndex: number }
|
||||
|
||||
Reference in New Issue
Block a user