pages235/lib/globalState.js
2023-08-15 19:51:57 +03:00

90 lines
2.6 KiB
JavaScript

//@ts-check
import { proxy } from 'valtio'
import { pointerLock } from './utils'
// todo: refactor structure with support of hideNext=false
/**
* @typedef {(HTMLElement & Record<string, any>)} Modal
* @typedef {{callback, label}} ContextMenuItem
*/
/** @type {Modal[]} */
export const activeModalStack = []
export const replaceActiveModalStack = (name, newModalStack = activeModalStacks[name]) => {
hideModal(undefined, undefined, { restorePrevious: false, force: true, })
activeModalStack.splice(0, activeModalStack.length, ...newModalStack)
// todo restore previous
}
/** @type {Record<string, Modal[]>} */
export const activeModalStacks = {}
window.activeModalStack = activeModalStack
export const customDisplayManageKeyword = 'custom'
const showModalInner = (/** @type {Modal} */ modal) => {
const cancel = modal.show?.()
if (cancel && cancel !== customDisplayManageKeyword) return false
if (cancel !== 'custom') modal.style.display = 'block'
return true
}
export const showModal = (/** @type {Modal} */ modal) => {
const curModal = activeModalStack.slice(-1)[0]
if (modal === curModal || !showModalInner(modal)) return
if (curModal) curModal.style.display = 'none'
activeModalStack.push(modal)
}
/**
*
* @param {*} data
* @param {{ force?: boolean, restorePrevious?: boolean, }} options
* @returns
*/
export const hideModal = (modal = activeModalStack.slice(-1)[0], data = undefined, options = {}) => {
const { force = false, restorePrevious = true } = options
if (!modal) return
let cancel = modal.hide?.(data)
if (force && cancel !== customDisplayManageKeyword) {
cancel = undefined
}
if (!cancel || cancel === customDisplayManageKeyword) {
if (cancel !== customDisplayManageKeyword) modal.style.display = 'none'
activeModalStack.pop()
const newModal = activeModalStack.slice(-1)[0]
if (newModal && restorePrevious) {
// would be great to ignore cancel I guess?
showModalInner(newModal)
}
return true
}
}
export const hideCurrentModal = (_data = undefined, preActions = undefined) => {
if (hideModal(undefined, undefined)) {
preActions?.()
if (document.getElementById('hud').style.display === 'none') {
showModal(document.getElementById('title-screen'))
} else {
pointerLock.requestPointerLock() // will work only if no modals left
}
}
}
// ---
export const currentContextMenu = proxy({ items: /** @type {ContextMenuItem[] | null} */[], x: 0, y: 0, })
export const showContextmenu = (/** @type {ContextMenuItem[]} */items, { clientX, clientY }) => {
Object.assign(currentContextMenu, {
items,
x: clientX,
y: clientY,
})
}