import { computed, getCurrentScope, onScopeDispose, reactive, ref, watch } from "vue"; import type { Rectangle } from "@/components/Workflow/Editor/modules/geometry"; import { useMagicKeys } from "@/composables/useMagicKeys"; import { useUserLocalStorage } from "@/composables/userLocalStorage"; import { defineScopedStore } from "./scopedStore"; import type { WorkflowCommentColor } from "./workflowEditorCommentStore"; export type CommentTool = "textComment" | "markdownComment" | "frameComment" | "freehandComment" | "freehandEraser"; export type EditorTool = "pointer" | "boxSelect" | CommentTool; export type InputCatcherEventType = | "pointerdown" | "pointerup" | "pointermove" | "pointerleave" | "temporarilyDisabled"; interface InputCatcherEventListener { type: InputCatcherEventType; callback: (event: InputCatcherEvent) => void; } export interface InputCatcherEvent { type: InputCatcherEventType; position: [number, number]; } export type WorkflowEditorToolbarStore = ReturnType; export const useWorkflowEditorToolbarStore = defineScopedStore("workflowEditorToolbarStore", () => { const snapActive = useUserLocalStorage("workflow-editor-toolbar-snap-active", false); const currentTool = ref("pointer"); const inputCatcherActive = ref(false); const inputCatcherEventListeners = new Set(); const snapDistance = ref<10 | 20 | 50 | 100 | 200>(10); const toolbarVisible = useUserLocalStorage("workflow-editor-toolbar-visible", true); const boxSelectMode = ref<"add" | "remove">("add"); const boxSelectRect = ref({ x: 0, y: 0, width: 0, height: 0 }); const commentOptions = reactive({ bold: false, italic: false, color: "none" as WorkflowCommentColor, textSize: 2, lineThickness: 5, smoothing: 2, }); const inputCatcherPressed = ref(false); function resetBoxSelect() { boxSelectRect.value = { x: 0, y: 0, width: 0, height: 0, }; } function onInputCatcherEvent(type: InputCatcherEventType, callback: InputCatcherEventListener["callback"]) { const listener = { type, callback, }; inputCatcherEventListeners.add(listener); if (getCurrentScope()) { onScopeDispose(() => { inputCatcherEventListeners.delete(listener); }); } } onInputCatcherEvent("pointerdown", () => (inputCatcherPressed.value = true)); onInputCatcherEvent("pointerup", () => (inputCatcherPressed.value = false)); onInputCatcherEvent("temporarilyDisabled", () => (inputCatcherPressed.value = false)); watch( () => inputCatcherActive.value, () => { if (!inputCatcherActive.value) { inputCatcherPressed.value = false; } }, ); const { shift, space, alt, ctrl } = useMagicKeys(); const modifierPressed = computed(() => shift?.value || space?.value || alt?.value || ctrl?.value); const inputCatcherTemporarilyDisabled = ref(false); const inputCatcherEnabled = computed(() => !modifierPressed.value && !inputCatcherTemporarilyDisabled.value); function emitInputCatcherEvent(type: InputCatcherEventType, event: InputCatcherEvent) { inputCatcherEventListeners.forEach((listener) => { if (listener.type === type) { listener.callback(event); } }); } return { toolbarVisible, snapActive, snapDistance, currentTool, inputCatcherActive, inputCatcherEnabled, inputCatcherTemporarilyDisabled, commentOptions, inputCatcherPressed, onInputCatcherEvent, emitInputCatcherEvent, boxSelectMode, boxSelectRect, resetBoxSelect, }; });