From cc9ff1c6b2ff79b4041aed641a859f3e5d7189c6 Mon Sep 17 00:00:00 2001 From: Paritosh Maurya Date: Sun, 4 May 2025 11:37:41 +0530 Subject: [PATCH 1/3] Added support for keyboard on component tab --- .../applet/src/modules/components/index.vue | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/packages/applet/src/modules/components/index.vue b/packages/applet/src/modules/components/index.vue index 929245e5..d6af8d2c 100644 --- a/packages/applet/src/modules/components/index.vue +++ b/packages/applet/src/modules/components/index.vue @@ -279,6 +279,99 @@ useEventListener('keydown', (event) => { } }) +useEventListener('keydown', (event) => { + if (!activeComponentId.value) + return + + switch (event.key) { + case 'ArrowRight': + handleArrowRight() + break + case 'ArrowLeft': + handleArrowLeft() + break + case 'ArrowDown': + handleArrowDown() + event.preventDefault() + break + case 'ArrowUp': + handleArrowUp() + event.preventDefault() + break + case ' ': + case 'Enter': { + handleEnter() + event.preventDefault() + break + } + } +}) + +function handleArrowRight() { + if (!expandedTreeNodes.value.includes(activeComponentId.value)) { + expandedTreeNodes.value.push(activeComponentId.value) + } +} + +function handleArrowLeft() { + if (expandedTreeNodes.value.includes(activeComponentId.value)) { + expandedTreeNodes.value.splice(expandedTreeNodes.value.indexOf(activeComponentId.value), 1) + } +} + +function handleArrowDown() { + const activeComponentIdIndex = flattenedTreeNodesIds.value.indexOf(activeComponentId.value) + const isActiveComponentExpanded = expandedTreeNodes.value.includes(activeComponentId.value) + + if (isActiveComponentExpanded && activeComponentIdIndex >= 0 && activeComponentIdIndex < flattenedTreeNodesIds.value.length - 1) { + activeComponentId.value = flattenedTreeNodesIds.value[activeComponentIdIndex + 1] + } + else if (activeComponentIdIndex === 0) { + return false + } + else { + const listIndex = treeNodeLinkedList.value.findIndex(arr => arr.includes(activeComponentId.value)) + const nextTree = treeNodeLinkedList.value[listIndex + 1] + if (nextTree) { + activeComponentId.value = nextTree[1] + } + } +} + +function handleArrowUp() { + const isSubTreeRoot = treeNodeLinkedList.value.some(chain => chain[1] === activeComponentId.value) + + if (isSubTreeRoot) { + activeComponentId.value = getPrevExpandedNode() + } + else { + const currentIndex = flattenedTreeNodesIds.value.indexOf(activeComponentId.value) + if (currentIndex > 0) { + activeComponentId.value = flattenedTreeNodesIds.value[currentIndex - 1] + } + } +} + +function handleEnter() { + const node = flattenedTreeNodes.value.find(item => item.id === activeComponentId.value) + if (!node?.children?.length) + return + + const index = expandedTreeNodes.value.indexOf(activeComponentId.value) + if (index === -1) + expandedTreeNodes.value.push(activeComponentId.value) + else expandedTreeNodes.value.splice(index, 1) +} + +function getPrevExpandedNode() { + const list = treeNodeLinkedList.value + const listIndex = list.findIndex((chain: string[]) => chain.includes(activeComponentId.value)) + if (listIndex > 0) { + return list[listIndex - 1].find(id => !expandedTreeNodes.value.includes(id)) || list[listIndex - 1][1] + } + return list[listIndex][0] +} + function scrollToComponent() { rpc.value.scrollToComponent(activeComponentId.value) } From 48db6b0fe9749499e4a0f8668e22be3cfbf0a94f Mon Sep 17 00:00:00 2001 From: mauryapari Date: Mon, 5 May 2025 19:27:10 +0530 Subject: [PATCH 2/3] Updated code for moving up and down the component tree --- .../applet/src/modules/components/index.vue | 130 ++++++++++++------ 1 file changed, 87 insertions(+), 43 deletions(-) diff --git a/packages/applet/src/modules/components/index.vue b/packages/applet/src/modules/components/index.vue index d6af8d2c..60ee13b3 100644 --- a/packages/applet/src/modules/components/index.vue +++ b/packages/applet/src/modules/components/index.vue @@ -11,7 +11,7 @@ import { vTooltip, VueButton, VueDialog, VueInput } from '@vue/devtools-ui' import { useElementSize, useEventListener, useToggle, watchDebounced } from '@vueuse/core' import { flatten, groupBy } from 'lodash-es' import { Pane, Splitpanes } from 'splitpanes' -import { computed, onUnmounted, ref, watch, watchEffect } from 'vue' +import { computed, nextTick, onUnmounted, ref, watch, watchEffect } from 'vue' import SelectiveList from '~/components/basic/SelectiveList.vue' import RootStateViewer from '~/components/state/RootStateViewer.vue' import ComponentTree from '~/components/tree/TreeViewer.vue' @@ -283,32 +283,40 @@ useEventListener('keydown', (event) => { if (!activeComponentId.value) return - switch (event.key) { - case 'ArrowRight': - handleArrowRight() - break - case 'ArrowLeft': - handleArrowLeft() - break - case 'ArrowDown': - handleArrowDown() - event.preventDefault() - break - case 'ArrowUp': - handleArrowUp() - event.preventDefault() - break - case ' ': - case 'Enter': { - handleEnter() - event.preventDefault() - break + nextTick(() => { + switch (event.key) { + case 'ArrowRight':{ + handleArrowRight() + break + } + case 'ArrowLeft': { + handleArrowLeft() + break + } + case 'ArrowDown': { + handleArrowDown() + event.preventDefault() + return false + } + case 'ArrowUp': { + handleArrowUp() + event.preventDefault() + break + } + case ' ': + case 'Enter': { + handleEnter() + break + } } - } + }) }) function handleArrowRight() { - if (!expandedTreeNodes.value.includes(activeComponentId.value)) { + const isPresentInExpandedNodes = expandedTreeNodes.value.includes(activeComponentId.value) + const hasChildren = flattenedTreeNodes.value.find(item => item.id === activeComponentId.value)?.children?.length + + if (!isPresentInExpandedNodes && hasChildren) { expandedTreeNodes.value.push(activeComponentId.value) } } @@ -330,25 +338,23 @@ function handleArrowDown() { return false } else { - const listIndex = treeNodeLinkedList.value.findIndex(arr => arr.includes(activeComponentId.value)) - const nextTree = treeNodeLinkedList.value[listIndex + 1] - if (nextTree) { - activeComponentId.value = nextTree[1] - } + activeComponentId.value = getNearestNextNode() } } function handleArrowUp() { - const isSubTreeRoot = treeNodeLinkedList.value.some(chain => chain[1] === activeComponentId.value) + const activeId = activeComponentId.value + const list = treeNodeLinkedList.value.find(item => item.includes(activeId)) + if (!list) + return - if (isSubTreeRoot) { - activeComponentId.value = getPrevExpandedNode() - } - else { - const currentIndex = flattenedTreeNodesIds.value.indexOf(activeComponentId.value) - if (currentIndex > 0) { - activeComponentId.value = flattenedTreeNodesIds.value[currentIndex - 1] - } + const activeItemListIndex = list.indexOf(activeId) + const activeItemParentIndex = activeItemListIndex > 0 ? activeItemListIndex - 1 : 0 + const parentId = list[activeItemParentIndex] + + const element = getNearestPreviousNode(parentId) + if (element) { + activeComponentId.value = element.id } } @@ -363,13 +369,51 @@ function handleEnter() { else expandedTreeNodes.value.splice(index, 1) } -function getPrevExpandedNode() { - const list = treeNodeLinkedList.value - const listIndex = list.findIndex((chain: string[]) => chain.includes(activeComponentId.value)) - if (listIndex > 0) { - return list[listIndex - 1].find(id => !expandedTreeNodes.value.includes(id)) || list[listIndex - 1][1] +function getNearestPreviousNode(parentId: string) { + const parentNode = flattenedTreeNodes.value.find(item => item.id === parentId) + if (!parentNode || !parentNode.children?.length) + return parentNode + + if (parentNode.children.length === 1) + return parentNode + + const indexInSiblings = parentNode?.children?.findIndex(item => item.id === activeComponentId.value) + + if (indexInSiblings <= 0) + return parentNode + + let prevSiblingNode = parentNode.children[indexInSiblings - 1] + + while (prevSiblingNode + && expandedTreeNodes.value.includes(prevSiblingNode.id) + && prevSiblingNode.children?.length) { + const lastChildNode = prevSiblingNode.children[prevSiblingNode.children.length - 1] + const next = getNearestPreviousNode(lastChildNode.id) + + if (!next || next.id === prevSiblingNode.id) + break + prevSiblingNode = next } - return list[listIndex][0] + + return prevSiblingNode || parentNode +} + +function getNearestNextNode() { + const linkedListTree = treeNodeLinkedList.value + const activeItemListIndex = [...linkedListTree] + .map((arr, index) => ({ arr, index })) + .reverse() + .find(({ arr }) => arr?.includes(activeComponentId.value)) + ?.index as number + + if (activeItemListIndex === -1) + return activeComponentId.value + const arr1 = linkedListTree[activeItemListIndex] + const arr2 = linkedListTree[activeItemListIndex + 1] + + const cloesestNodeIndex = arr2?.findIndex((val, index) => val !== arr1[index]) ?? -1 + + return cloesestNodeIndex !== -1 ? arr2[cloesestNodeIndex] : activeComponentId.value } function scrollToComponent() { From 717d5c5f4cda69305bdcfad7f152f000bf882893 Mon Sep 17 00:00:00 2001 From: mauryapari Date: Mon, 5 May 2025 19:41:40 +0530 Subject: [PATCH 3/3] Modified a condition to shorten it --- packages/applet/src/modules/components/index.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/applet/src/modules/components/index.vue b/packages/applet/src/modules/components/index.vue index 60ee13b3..a7dd4721 100644 --- a/packages/applet/src/modules/components/index.vue +++ b/packages/applet/src/modules/components/index.vue @@ -400,14 +400,11 @@ function getNearestPreviousNode(parentId: string) { function getNearestNextNode() { const linkedListTree = treeNodeLinkedList.value - const activeItemListIndex = [...linkedListTree] - .map((arr, index) => ({ arr, index })) - .reverse() - .find(({ arr }) => arr?.includes(activeComponentId.value)) - ?.index as number + const activeItemListIndex = [...linkedListTree].findLastIndex(arr => arr?.includes(activeComponentId.value)) if (activeItemListIndex === -1) return activeComponentId.value + const arr1 = linkedListTree[activeItemListIndex] const arr2 = linkedListTree[activeItemListIndex + 1]