Write custom Path and Segment classes
Also fixes how pinning works in some edge cases.
This commit is contained in:
parent
0b485e6cfe
commit
b29b3c1e4e
6 changed files with 149 additions and 77 deletions
|
|
@ -1,47 +1,49 @@
|
|||
import { pathAncestors, pathLiesOn, pathSlice } from "@/util";
|
||||
import { Segment, Path as UiPath } from "@/lib/path";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, watchEffect } from "vue";
|
||||
|
||||
export const useUiStore = defineStore("ui", () => {
|
||||
const anchorId = ref<string>();
|
||||
const focusPath = ref<string>("");
|
||||
const focusPath = ref<UiPath>(new UiPath());
|
||||
const openPaths = ref<Set<string>>(new Set());
|
||||
const pinned = ref<string>(); // The last two segments of the path
|
||||
const pinned = ref<{ segment: Segment; parentId?: string }>();
|
||||
|
||||
// Ensure all nodes on the focusPath are unfolded.
|
||||
watchEffect(() => {
|
||||
// The node pointed to by the path itself doesn't need to be unfolded.
|
||||
for (const ancestor of pathAncestors(focusPath.value).slice(1)) {
|
||||
openPaths.value.add(ancestor);
|
||||
for (const ancestor of focusPath.value.ancestors().slice(1)) {
|
||||
setOpen(ancestor, true);
|
||||
}
|
||||
});
|
||||
|
||||
function isOpen(path: string): boolean {
|
||||
return openPaths.value.has(path);
|
||||
function isOpen(path: UiPath): boolean {
|
||||
return openPaths.value.has(path.fmt());
|
||||
}
|
||||
|
||||
function setOpen(path: string, value: boolean) {
|
||||
// Move the focusPath if necessary
|
||||
if (!value && isOpen(path) && pathLiesOn(path, focusPath.value)) {
|
||||
focusPath.value = path;
|
||||
}
|
||||
|
||||
function setOpen(path: UiPath, value: boolean) {
|
||||
// Don't update openPaths unnecessarily.
|
||||
// Just in case vue itself doesn't debounce Set operations.
|
||||
if (value && !isOpen(path)) openPaths.value.add(path);
|
||||
else if (!value && isOpen(path)) openPaths.value.delete(path);
|
||||
if (value && !isOpen(path)) {
|
||||
openPaths.value.add(path.fmt());
|
||||
} else if (!value && isOpen(path)) {
|
||||
// Move the focusPath if necessary
|
||||
if (path.isPrefixOf(focusPath.value)) focusPath.value = path;
|
||||
|
||||
openPaths.value.delete(path.fmt());
|
||||
}
|
||||
}
|
||||
|
||||
function toggleOpen(path: string) {
|
||||
function toggleOpen(path: UiPath) {
|
||||
setOpen(path, !isOpen(path));
|
||||
}
|
||||
|
||||
function isPinned(path: string): boolean {
|
||||
return pathSlice(path, -2) === pinned.value;
|
||||
function isPinned(segment: Segment, parentId?: string): boolean {
|
||||
if (!pinned.value) return false;
|
||||
return pinned.value.segment.eq(segment) && pinned.value.parentId === parentId;
|
||||
}
|
||||
|
||||
function setPinned(path: string) {
|
||||
pinned.value = pathSlice(path, -2);
|
||||
function setPinned(segment: Segment, parentId?: string) {
|
||||
pinned.value = { segment, parentId };
|
||||
}
|
||||
|
||||
function unsetPinned() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue