Skip to content

Commit

Permalink
decouple node inspector from right hand panel
Browse files Browse the repository at this point in the history
  • Loading branch information
ElectronicBlueberry committed Sep 27, 2024
1 parent 1664e4d commit 0b346aa
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 141 deletions.
139 changes: 139 additions & 0 deletions client/src/components/Common/DraggableSeparator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<script setup lang="ts">
import { useDebounce, useDraggable } from "@vueuse/core";
import { computed, ref, watch } from "vue";
import { useEmit } from "@/composables/eventEmitter";
import { useClamp } from "@/composables/math";
import { useAnimationFrameThrottle } from "@/composables/throttle";
const props = withDefaults(
defineProps<{
position: number;
min?: number;
max?: number;
showDelay?: number;
keyboardStepSize?: number;
side: "left" | "right";
additionalOffset?: number;
}>(),
{
showDelay: 100,
keyboardStepSize: 50,
min: -Infinity,
max: Infinity,
additionalOffset: 0,
}
);
const emit = defineEmits<{
(e: "positionChanged", position: number): void;
(e: "visibilityChanged", isVisible: boolean): void;
(e: "dragging", isDragging: boolean): void;
}>();
const { throttle } = useAnimationFrameThrottle();
const draggable = ref<HTMLButtonElement | null>(null);
const { position: draggablePosition, isDragging } = useDraggable(draggable, {
preventDefault: true,
exact: true,
initialValue: { x: props.position, y: 0 },
});
useEmit(isDragging, emit, "dragging");
const handlePosition = useClamp(
ref(props.position),
() => props.min,
() => props.max
);
useEmit(handlePosition, emit, "positionChanged");
watch(
() => props.position,
() => (handlePosition.value = props.position)
);
function updatePosition() {
handlePosition.value = draggablePosition.value.x;
}
watch(
() => draggablePosition.value,
() => throttle(updatePosition)
);
const hoverDraggable = ref(false);
const hoverDraggableDebounced = useDebounce(
hoverDraggable,
computed(() => props.showDelay)
);
const showHover = computed(() => (hoverDraggable.value && hoverDraggableDebounced.value) || isDragging.value);
useEmit(showHover, emit, "visibilityChanged");
function onKeyLeft() {
handlePosition.value -= props.keyboardStepSize;
}
function onKeyRight() {
handlePosition.value += props.keyboardStepSize;
}
const style = computed(() => ({
"--position": handlePosition.value + "px",
}));
</script>

<template>
<button
ref="draggable"
class="drag-handle"
:class="`side-${props.side}`"
:style="style"
@mouseenter="hoverDraggable = true"
@focusin="hoverDraggable = true"
@mouseout="hoverDraggable = false"
@focusout="hoverDraggable = false"
@keydown.left="onKeyLeft"
@keydown.right="onKeyRight">
<span class="sr-only"> Resizable drag handle </span>
</button>
</template>

<style scoped lang="scss">
$border-width: 8px;
.drag-handle {
--position: 0;
background-color: transparent;
background: none;
border: none;
border-radius: 0;
position: absolute;
width: $border-width;
padding: 0;
height: 100%;
z-index: 10000;
--hover-expand: 4px;
&:hover {
cursor: ew-resize;
width: calc($border-width + var(--hover-expand));
}
&.side-left {
left: var(--position);
}
&.side-right {
right: var(--position);
}
}
</style>
143 changes: 10 additions & 133 deletions client/src/components/Panels/FlexPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faChevronLeft, faChevronRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { useDebounce, useDraggable } from "@vueuse/core";
import { computed, ref, watch } from "vue";
import { useTimeoutThrottle } from "@/composables/throttle";
import { determineWidth } from "./utilities";
const { throttle } = useTimeoutThrottle(10);
import DraggableSeparator from "../Common/DraggableSeparator.vue";
library.add(faChevronLeft, faChevronRight);
Expand All @@ -28,26 +23,18 @@ const props = withDefaults(defineProps<Props>(), {
defaultWidth: 300,
});
const draggable = ref<HTMLElement | null>(null);
const root = ref<HTMLElement | null>(null);
const panelWidth = ref(props.defaultWidth);
const show = ref(true);
const { position, isDragging } = useDraggable(draggable, {
preventDefault: true,
exact: true,
});
const hoverDraggable = ref(false);
const hoverDraggableDebounced = useDebounce(hoverDraggable, 100);
const showHover = computed(() => (hoverDraggable.value && hoverDraggableDebounced.value) || isDragging.value);
const root = ref<HTMLElement | null>(null);
const show = ref(true);
const showToggle = ref(false);
const hoverToggle = ref(false);
const hoverDraggableOrToggle = computed(
() => (hoverDraggableDebounced.value || hoverToggle.value) && !isDragging.value
);
const isHoveringDragHandle = ref(false);
const isDragging = ref(false);
const hoverDraggableOrToggle = computed(() => (isHoveringDragHandle.value || hoverToggle.value) && !isDragging.value);
const toggleLinger = 500;
const toggleShowDelay = 600;
Expand All @@ -70,72 +57,6 @@ watch(
}
);
/** Watch position changes and adjust width accordingly */
watch(position, () => {
throttle(() => {
if (!root.value || !draggable.value) {
return;
}
const rectRoot = root.value.getBoundingClientRect();
const rectDraggable = draggable.value.getBoundingClientRect();
panelWidth.value = determineWidth(
rectRoot,
rectDraggable,
props.minWidth,
props.maxWidth,
props.side,
position.value.x
);
});
});
/** If the `maxWidth` changes, prevent the panel from exceeding it */
watch(
() => props.maxWidth,
(newVal) => {
if (newVal && panelWidth.value > newVal) {
panelWidth.value = props.maxWidth;
}
},
{ immediate: true }
);
/** If the `minWidth` changes, ensure the panel width is at least the `minWidth` */
watch(
() => props.minWidth,
(newVal) => {
if (newVal && panelWidth.value < newVal) {
panelWidth.value = newVal;
}
},
{ immediate: true }
);
function onKeyLeft() {
if (props.side === "left") {
decreaseWidth();
} else {
increaseWidth();
}
}
function onKeyRight() {
if (props.side === "left") {
increaseWidth();
} else {
decreaseWidth();
}
}
function increaseWidth(by = 50) {
panelWidth.value = Math.min(panelWidth.value + by, props.maxWidth);
}
function decreaseWidth(by = 50) {
panelWidth.value = Math.max(panelWidth.value - by, props.minWidth);
}
const sideClasses = computed(() => ({
left: props.side === "left",
right: props.side === "right",
Expand All @@ -148,19 +69,9 @@ const sideClasses = computed(() => ({
:id="side"
ref="root"
class="flex-panel"
:class="{ ...sideClasses, 'show-hover': showHover }"
:class="{ ...sideClasses }"
:style="`--width: ${panelWidth}px`">
<button
ref="draggable"
class="drag-handle"
@mouseenter="hoverDraggable = true"
@focusin="hoverDraggable = true"
@mouseout="hoverDraggable = false"
@focusout="hoverDraggable = false"
@keydown.left="onKeyLeft"
@keydown.right="onKeyRight">
<span class="sr-only"> Side panel drag handle </span>
</button>
<DraggableSeparator :position="panelWidth" :side="props.side"></DraggableSeparator>

<button
v-if="props.collapsible"
Expand Down Expand Up @@ -235,14 +146,6 @@ $border-width: 6px;
&::after {
right: -1px;
}
.drag-handle {
right: -$border-width;
&:hover {
right: calc(-1 * $border-width - var(--hover-expand) / 2);
}
}
}
&.right {
Expand All @@ -251,32 +154,6 @@ $border-width: 6px;
&::after {
left: -1px;
}
.drag-handle {
left: -$border-width;
&:hover {
left: calc(-1 * $border-width - var(--hover-expand) / 2);
}
}
}
}
.drag-handle {
background: none;
border: none;
border-radius: 0;
position: absolute;
width: $border-width;
padding: 0;
height: 100%;
z-index: 10000;
--hover-expand: 4px;
&:hover {
cursor: ew-resize;
width: calc($border-width + var(--hover-expand));
}
}
Expand Down
13 changes: 5 additions & 8 deletions client/src/components/Workflow/Editor/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@
@onChange="onChange"
@onRemove="onRemove"
@onUpdateStepPosition="onUpdateStepPosition">
<NodeInspector v-if="activeStep" :step="activeStep"></NodeInspector>
</WorkflowGraph>
</div>
<FlexPanel side="right">
<!--FlexPanel side="right">
<div class="unified-panel bg-white">
<div ref="rightPanelElement" class="unified-panel-body workflow-right p-2">
<div v-if="!initialLoading" class="position-relative h-100">
Expand All @@ -178,7 +179,7 @@
</div>
</div>
</div>
</FlexPanel>
</FlexPanel-->
</template>
</div>
</template>
Expand Down Expand Up @@ -216,6 +217,7 @@ import reportDefault from "./reportDefault";
import WorkflowLint from "./Lint.vue";
import MessagesModal from "./MessagesModal.vue";
import NodeInspector from "./NodeInspector.vue";
import RefactorConfirmationModal from "./RefactorConfirmationModal.vue";
import SaveChangesModal from "./SaveChangesModal.vue";
import StateUpgradeModal from "./StateUpgradeModal.vue";
Expand All @@ -224,25 +226,19 @@ import WorkflowGraph from "./WorkflowGraph.vue";
import ActivityBar from "@/components/ActivityBar/ActivityBar.vue";
import MarkdownEditor from "@/components/Markdown/MarkdownEditor.vue";
import MarkdownToolBox from "@/components/Markdown/MarkdownToolBox.vue";
import FlexPanel from "@/components/Panels/FlexPanel.vue";
import ToolPanel from "@/components/Panels/ToolPanel.vue";
import WorkflowPanel from "@/components/Panels/WorkflowPanel.vue";
import UndoRedoStack from "@/components/UndoRedo/UndoRedoStack.vue";
import FormDefault from "@/components/Workflow/Editor/Forms/FormDefault.vue";
import FormTool from "@/components/Workflow/Editor/Forms/FormTool.vue";
library.add(faArrowLeft, faArrowRight, faHistory);
export default {
components: {
ActivityBar,
MarkdownEditor,
FlexPanel,
SaveChangesModal,
StateUpgradeModal,
ToolPanel,
FormDefault,
FormTool,
WorkflowAttributes,
WorkflowLint,
RefactorConfirmationModal,
Expand All @@ -252,6 +248,7 @@ export default {
UndoRedoStack,
WorkflowPanel,
MarkdownToolBox,
NodeInspector,
},
props: {
workflowId: {
Expand Down
Loading

0 comments on commit 0b346aa

Please sign in to comment.