import type { VNode } from 'vue'; import type { ModalHeaderIcon } from './modal'; import { globalState } from '../../app/global-state'; import { MobileModeConfig } from '../../common/mobile-mode-config'; import { PortalUtils } from '../../common/utils/utils'; export enum ModalMobileMode { Default = 0, BottomSheetModal = 1, FullScreen = 2, } /** * Modal presentation config + shared presentation decisions, kept out of * `modal.tsx` so non-component code (e.g. `common/dialog-utils.ts`) can import * it without pulling in the whole Modal component graph. `modal.tsx` * re-exports everything here, so component consumers keep importing from * `./modal`. */ export class ModalConfig { static defaultPortalTarget = 'body'; static defaultMobileMode = ModalMobileMode.BottomSheetModal; static renderModalHeaderIcon: (icon: ModalHeaderIcon) => VNode = null; /** * Decides whether a modal with the given `mobileMode` should present as a * bottom sheet right now. A sheet is used only on an actual mobile device, * in portrait orientation (in landscape the sheet would consume most of * the scarce vertical space), and on viewports up to * `MobileModeConfig.sheetModalMaxWidth` wide. */ static useBottomSheet(mobileMode?: ModalMobileMode): boolean { if (!PortalUtils.treatAsMobileDevice()) { return false; } if (globalState.innerWidth > MobileModeConfig.sheetModalMaxWidth) { return false; } if (PortalUtils.isLandscape()) { return false; } if (mobileMode == ModalMobileMode.BottomSheetModal) { return true; } else if (mobileMode == null && ModalConfig.defaultMobileMode == ModalMobileMode.BottomSheetModal) { return true; } return false; } }