import { defineStore } from 'pinia'; import { computed, nextTick, ref, watch } from 'vue'; const resetSmoothAnimation = 300; const edgePx = 12; export enum FloatingState { REGULAR = 'regular', VERTICAL_SQUASH = 'vertical_squash', HORIZONTAL_SQUASH = 'horizontal_squash', } export const useMcadFloatingStore = defineStore('mcad-floating', () => { const x = ref(16); const y = ref(16); const state = ref(FloatingState.REGULAR); const smooth = ref(false); const isDragging = ref(false); addEventListener('resize', (event) => { smoothXY(16, 16); }); function smoothXY(newX: number, newY: number) { smooth.value = true; x.value = newX; y.value = newY; setTimeout(() => { smooth.value = false; }, resetSmoothAnimation); } function smoothDeltaX(newX: number) { smooth.value = true; x.value += newX; setTimeout(() => { smooth.value = false; }, resetSmoothAnimation); } function smoothDeltaY(newY: number) { smooth.value = true; y.value += newY; setTimeout(() => { smooth.value = false; }, resetSmoothAnimation); } const style = computed(() => { return { transform: 'translate(' + x.value + 'px, ' + y.value + 'px)', transition: smooth.value ? `all ${resetSmoothAnimation}ms ease-in-out` : '', }; }); function getDimensions() { const self = document.getElementById('drag-set'); const parent = self?.parentElement; const currentHeight = self?.clientHeight || 0; const parentY = (parent?.clientHeight || 0) - currentHeight; const currentWidth = self?.clientWidth || 0; const parentX = (parent?.clientWidth || 0) - currentWidth; return { parentX, parentY, currentWidth, currentHeight, }; } // Update the edge state if sticky function setEdge() { const { parentX, parentY } = getDimensions(); if (x.value <= edgePx || x.value >= parentX - edgePx) { state.value = FloatingState.VERTICAL_SQUASH; } else if (y.value <= edgePx || y.value >= parentY - edgePx) { state.value = FloatingState.HORIZONTAL_SQUASH; } else { state.value = FloatingState.REGULAR; } } // Update the edge state if sticky async function open() { const { parentX, parentY } = getDimensions(); if (y.value >= parentY - edgePx) { await nextTick(); smoothDeltaY(-(160 + 20)); } if (x.value >= parentX - edgePx) { await nextTick(); smoothDeltaX(-266); } if (y.value <= edgePx) { await nextTick(); smoothDeltaY(20); } if (x.value <= edgePx) { await nextTick(); smoothDeltaX(20); } setEdge(); await reposition(); setEdge(); const { currentHeight } = getDimensions(); if (y.value >= parentY - edgePx) { await nextTick(); smoothDeltaY(-currentHeight); } } // If changing the edge state moves the container out of edge, reposition async function reposition() { const { parentX, parentY, currentWidth, currentHeight } = getDimensions(); if (y.value >= parentY - edgePx) { await nextTick(); const { currentHeight: latestHeight } = getDimensions(); smoothDeltaY(currentHeight - latestHeight); } if (x.value >= parentX - edgePx) { await nextTick(); const { currentWidth: latestWidth } = getDimensions(); smoothDeltaX(currentWidth - latestWidth); } } watch(isDragging, async (dragging) => { if (!dragging) { setEdge(); await reposition(); setEdge(); } }); return { style, state, x, y, isDragging, open, setEdge }; });