Skip to content

Commit

Permalink
feat: auto focus for tree view
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Aug 9, 2024
1 parent 54857b6 commit 4145010
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
8 changes: 1 addition & 7 deletions components/CodeEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ if (props.input) {
range: monaco.Range.fromPositions(start, end),
options: {
isWholeLine: false,
className: 'input-editor-highlight',
className: 'ast-highlight',
},
},
])
Expand All @@ -79,9 +79,3 @@ if (props.input) {
</div>
</MonacoEditor>
</template>

<style>
.input-editor-highlight {
--at-apply: 'bg-yellow-400/30 dark:bg-yellow-600/30';
}
</style>
3 changes: 1 addition & 2 deletions components/OutputContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ watch(outputView, (view) => {
JSON
</button>
</div>
<!-- TODO implement auto-focus on tree view -->
<label v-if="outputView === 'json'">
<label>
<input
:checked="autoFocus"
type="checkbox"
Expand Down
42 changes: 37 additions & 5 deletions components/ast/Property.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const openable = computed(
Object.keys(props.value).length > 0,
)
const isHover = computed(() => {
const isHovering = computed(() => {
if (Array.isArray(props.value)) {
return props.value.some((v) => checkRange(getRange(v)))
}
Expand All @@ -41,15 +41,20 @@ const isHover = computed(() => {
})
const openManual = ref<boolean>()
const open = computed(
() => openable.value && (openManual.value ?? (props.open || isHover.value)),
() =>
openable.value &&
(openManual.value ?? (props.open || (autoFocus.value && isHovering.value))),
)
const valueCreated = ref(false)
watch(open, () => (valueCreated.value ||= open.value), { immediate: true })
function toggleOpen() {
if (!openable.value) return
if (
openManual.value !== undefined &&
openManual.value !== (props.open || isHover.value)
openManual.value !== (props.open || isHovering.value)
) {
openManual.value = undefined
} else {
Expand Down Expand Up @@ -81,12 +86,33 @@ function handleMouseLeave() {
outputHoverRange.value = undefined
}
}
const container = ref<HTMLDivElement>()
const exactHover = ref(false)
function handleSubHoverChange(subHovering: boolean) {
exactHover.value = isHovering.value && !subHovering
}
watch(
[autoFocus, exactHover, isHovering, container],
([autoFocus, exactHover, isHovering, container]) => {
if (autoFocus && exactHover && isHovering && container) {
requestAnimationFrame(() => container.scrollIntoView({ block: 'center' }))
}
},
{ immediate: true },
)
defineExpose({ isHovering })
</script>

<template>
<div
v-if="show"
ref="container"
relative
:class="isHovering && exactHover && 'ast-highlight'"
@mouseover="handleMouseOver"
@mouseleave="handleMouseLeave"
>
Expand Down Expand Up @@ -117,7 +143,13 @@ function handleMouseLeave() {
v-text="title"
/>&nbsp;</span
>
<AstValue v-if="!openable || open" :data="value" />
<AstSummaryValue v-else :data="value" @toggle="toggleOpen" />
<span v-if="!openable || valueCreated" v-show="!openable || open">
<AstValue :data="value" @update:hover="handleSubHoverChange" />
</span>
<AstSummaryValue
v-if="openable && !open"
:data="value"
@toggle="toggleOpen"
/>
</div>
</template>
12 changes: 11 additions & 1 deletion components/ast/Value.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<script setup lang="ts">
import type { AstProperty } from '#components'
const props = defineProps<{ data: any }>()
const emit = defineEmits<{
'update:hover': [value: boolean]
}>()
const hasChildren = computed(
() =>
Expand All @@ -14,14 +18,20 @@ const value = computed<string | undefined>(() => {
return props.data == null ? String(props.data) : JSON.stringify(props.data)
})
const valueColor = useHighlightColor(value)
const properties = useTemplateRefsList<InstanceType<typeof AstProperty>>()
watchEffect(() => {
const hovering = properties.value.some((p) => p.isHovering)
emit('update:hover', hovering)
})
</script>

<template>
<template v-if="typeof data === 'object' && data != null">
<AstBrackets :data>
<div v-if="hasChildren" ml6>
<template v-for="(item, key) of data" :key="key">
<AstProperty :id="key" :value="item" />
<AstProperty :id="key" :ref="properties.set" :value="item" />
</template>
</div>
</AstBrackets>
Expand Down
4 changes: 4 additions & 0 deletions styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ option {
background-color: transparent !important;
}

.ast-highlight {
--at-apply: 'bg-yellow-400/30 dark:bg-yellow-400/20';
}

/* Color Mode transition */
::view-transition-old(root),
::view-transition-new(root) {
Expand Down

0 comments on commit 4145010

Please sign in to comment.