import type { DragElementState } from '../composables/useDragElements' import { breakpointsTailwind, isClient, useActiveElement, useBreakpoints, useFullscreen, useLocalStorage, useMagicKeys, useToggle, useWindowSize } from '@vueuse/core' import { computed, reactive, ref, shallowRef } from 'vue' import { slideAspect } from '../env' export const showRecordingDialog = ref(false) export const showInfoDialog = ref(false) export const showGotoDialog = ref(false) export const showOverview = ref(false) /** * Skip slides transition when triggered by HMR. * Will reset automatically after user navigations */ export const hmrSkipTransition = ref(false) export const disableTransition = ref(false) export const shortcutsEnabled = ref(true) // Use a locking mechanism to support multiple simultaneous locks // and avoid race conditions. Race conditions may occur, for example, // when locking shortcuts on editor focus and moving from one editor // to another, as blur events can be triggered after focus. const shortcutsLocks = reactive(new Set()) export const shortcutsLocked = computed(() => shortcutsLocks.size > 0) export function lockShortcuts() { const lock = Symbol('shortcuts lock') shortcutsLocks.add(lock) return () => { shortcutsLocks.delete(lock) } } export const breakpoints = useBreakpoints({ xs: 460, ...breakpointsTailwind, }) export const windowSize = useWindowSize() export const magicKeys = useMagicKeys() export const isScreenVertical = computed(() => windowSize.height.value - windowSize.width.value / slideAspect.value > 120) export const fullscreen = useFullscreen(isClient ? document.body : null) export const activeElement = useActiveElement() export const isInputting = computed(() => ['INPUT', 'TEXTAREA'].includes(activeElement.value?.tagName || '')) export const isOnFocus = computed(() => ['BUTTON', 'A'].includes(activeElement.value?.tagName || '')) export const currentCamera = useLocalStorage('slidev-camera', 'default', { listenToStorageChanges: false }) export const currentMic = useLocalStorage('slidev-mic', 'default', { listenToStorageChanges: false }) export const slideScale = useLocalStorage('slidev-scale', 0) export const wakeLockEnabled = useLocalStorage('slidev-wake-lock', true) export const hideCursorIdle = useLocalStorage('slidev-hide-cursor-idle', true) export const skipExportPdfTip = useLocalStorage('slidev-skip-export-pdf-tip', false) export const captureDelay = useLocalStorage('slidev-export-capture-delay', 400, { listenToStorageChanges: false }) export const showPresenterCursor = useLocalStorage('slidev-presenter-cursor', true, { listenToStorageChanges: false }) export const cursorStyle = useLocalStorage<'cursor' | 'laser'>('slidev-cursor-style', 'cursor', { listenToStorageChanges: false }) export function togglePresenterCursor() { showPresenterCursor.value = !showPresenterCursor.value } export const showEditor = useLocalStorage('slidev-show-editor', false, { listenToStorageChanges: false }) export const isEditorVertical = useLocalStorage('slidev-editor-vertical', false, { listenToStorageChanges: false }) export const editorWidth = useLocalStorage('slidev-editor-width', isClient ? window.innerWidth * 0.4 : 318, { listenToStorageChanges: false }) export const editorHeight = useLocalStorage('slidev-editor-height', isClient ? window.innerHeight * 0.4 : 300, { listenToStorageChanges: false }) export const activeDragElement = shallowRef(null) export const presenterNotesFontSize = useLocalStorage('slidev-presenter-font-size', 1, { listenToStorageChanges: false }) export const presenterLayout = useLocalStorage('slidev-presenter-layout', 1, { listenToStorageChanges: false }) export const viewerCssFilterDefaults = { invert: false, contrast: 1, brightness: 1, hueRotate: 0, saturate: 1, sepia: 0, } export const viewerCssFilter = useLocalStorage( 'slidev-viewer-css-filter', viewerCssFilterDefaults, { listenToStorageChanges: false, mergeDefaults: true, deep: true }, ) export const hasViewerCssFilter = computed(() => { return (Object.keys(viewerCssFilterDefaults) as (keyof typeof viewerCssFilterDefaults)[]) .some(k => viewerCssFilter.value[k] !== viewerCssFilterDefaults[k]) }) export function togglePresenterLayout() { presenterLayout.value = presenterLayout.value + 1 if (presenterLayout.value > 3) presenterLayout.value = 1 } export function increasePresenterFontSize() { presenterNotesFontSize.value = Math.min(2, presenterNotesFontSize.value + 0.1) } export function decreasePresenterFontSize() { presenterNotesFontSize.value = Math.max(0.5, presenterNotesFontSize.value - 0.1) } export const toggleOverview = useToggle(showOverview) export const syncDirections = useLocalStorage( 'slidev-sync-directions', { viewerSend: true, viewerReceive: true, presenterSend: true, presenterReceive: true, }, { listenToStorageChanges: false, mergeDefaults: true, }, )