{"version":3,"file":"modal.obs.js","sources":["../../../Framework/Controls/modal.obs"],"sourcesContent":["<!-- Copyright by the Spark Development Network; Licensed under the Rock Community License -->\r\n<template>\r\n <teleport :to=\"container\" v-if=\"modelValue\">\r\n <div :class=\"modalWrapperClasses\">\r\n <div class=\"modal-backdrop\" style=\"z-index: 1050;\"></div>\r\n\r\n <div @click.stop=\"onScrollableClick\" class=\"modal-scrollable\" style=\"z-index: 1050;\">\r\n <div @click.stop\r\n class=\"modal container modal-content rock-modal rock-modal-frame modal-overflow\"\r\n :class=\"{ 'animated shake': isShaking }\"\r\n aria-hidden=\"false\"\r\n tabindex=\"-1\"\r\n role=\"dialog\"\r\n style=\"display: block; margin-top: 0px;\">\r\n <div class=\"modal-header\">\r\n <button v-if=\"!isCloseButtonHidden\" @click=\"onClose\" class=\"close\" aria-hidden=\"true\" type=\"button\">×</button>\r\n <template v-if=\"title\">\r\n <h3 class=\"modal-title\">{{ title }}</h3>\r\n <small v-if=\"subtitle\">{{ subtitle }}</small>\r\n </template>\r\n <slot v-else name=\"header\" />\r\n </div>\r\n\r\n <RockForm @submit=\"onSubmit\" hideErrors @visibleValidationChanged=\"onVisibleValidationChanged\">\r\n <div class=\"modal-body\">\r\n <RockValidation :errors=\"validationErrors\" />\r\n\r\n <div ref=\"modalBodyElement\">\r\n <slot />\r\n </div>\r\n\r\n <div ref=\"modalBodyPaddingElement\" style=\"transition: 0.15s padding-bottom\"></div>\r\n </div>\r\n\r\n <div v-if=\"!isFooterHidden\" class=\"modal-footer\">\r\n <RockButton v-if=\"cancelText\" @click=\"onClose\" btnType=\"link\">{{ cancelText }}</RockButton>\r\n <RockButton v-if=\"saveText\" type=\"submit\" btnType=\"primary\" :disabled=\"isSaveButtonDisabled\">{{ saveText }}</RockButton>\r\n <slot name=\"customButtons\" />\r\n </div>\r\n </RockForm>\r\n </div>\r\n </div>\r\n </div>\r\n </teleport>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { nextTick, onBeforeUnmount, PropType, ref, watch } from \"vue\";\r\n import RockForm from \"./rockForm.obs\";\r\n import RockButton from \"./rockButton.obs\";\r\n import RockValidation from \"./rockValidation.obs\";\r\n import { trackModalState } from \"@Obsidian/Utility/page\";\r\n import { FormError } from \"@Obsidian/Utility/form\";\r\n\r\n const props = defineProps({\r\n modelValue: {\r\n type: Boolean as PropType<boolean>,\r\n required: true\r\n },\r\n\r\n modalWrapperClasses: {\r\n type: String as PropType<string>,\r\n default: \"\"\r\n },\r\n\r\n title: {\r\n type: String as PropType<string>,\r\n default: \"\"\r\n },\r\n\r\n subtitle: {\r\n type: String as PropType<string>,\r\n default: \"\"\r\n },\r\n\r\n cancelText: {\r\n type: String as PropType<string>,\r\n default: \"Cancel\"\r\n },\r\n\r\n saveText: {\r\n type: String as PropType<string>,\r\n default: \"\"\r\n },\r\n\r\n isFooterHidden: {\r\n type: Boolean as PropType<boolean>,\r\n default: false\r\n },\r\n\r\n isSaveButtonDisabled: {\r\n type: Boolean as PropType<boolean>,\r\n default: false\r\n },\r\n\r\n isCloseButtonHidden: {\r\n type: Boolean as PropType<boolean>,\r\n default: false\r\n },\r\n\r\n clickBackdropToClose: {\r\n type: Boolean as PropType<boolean>,\r\n default: false\r\n }\r\n });\r\n\r\n const emit = defineEmits<{\r\n (e: \"update:modelValue\", value: boolean): void;\r\n (e: \"closeModal\"): void;\r\n (e: \"save\"): void;\r\n }>();\r\n\r\n // #region Values\r\n\r\n const internalModalVisible = ref(props.modelValue);\r\n const container = ref(document.fullscreenElement ?? document.body);\r\n const validationErrors = ref<FormError[]>([]);\r\n\r\n /** Used to determine if shaking should be currently performed. */\r\n const isShaking = ref(false);\r\n\r\n // These values are used to automatically resize the modal if an absolute\r\n // popup like a DataView picker is used inside the modal body.\r\n const modalBodyElement = ref<HTMLElement | null>(null);\r\n const modalBodyPaddingElement = ref<HTMLElement | null>(null);\r\n let legacyOverflowTimer: number | undefined;\r\n const overflowMutationObserver: MutationObserver | undefined = MutationObserver ? new MutationObserver(onOverflowMutation) : undefined;\r\n const overflowResizeObserver: ResizeObserver | undefined = ResizeObserver ? new ResizeObserver(onOverflowResize) : undefined;\r\n\r\n // #endregion\r\n\r\n // #region Functions\r\n\r\n /**\r\n * Adjusts the height of the modal to fit the content. This handles\r\n * cases where something like a DataViewPicker is opened up that has\r\n * an inner popup.\r\n */\r\n function adjustOverflowPadding(): void {\r\n if (modalBodyElement.value && modalBodyPaddingElement.value) {\r\n if (modalBodyElement.value.scrollHeight !== modalBodyElement.value.clientHeight) {\r\n let existingPadding = 0;\r\n try {\r\n existingPadding = parseFloat(window.getComputedStyle(modalBodyPaddingElement.value, null).getPropertyValue(\"padding-bottom\"));\r\n }\r\n catch {\r\n existingPadding = 0;\r\n }\r\n\r\n const totalPadding = modalBodyElement.value.scrollHeight - modalBodyElement.value.clientHeight;\r\n\r\n if (existingPadding !== totalPadding) {\r\n modalBodyPaddingElement.value.style.paddingBottom = `${totalPadding}px`;\r\n }\r\n }\r\n else if (modalBodyPaddingElement.value.style.paddingBottom !== \"\") {\r\n modalBodyPaddingElement.value.style.paddingBottom = \"\";\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Timer callback when the observers are not supported by the browser.\r\n * Check the overflow padding to see if it needs to be adjusted.\r\n */\r\n function detectLegacyOverflow(): void {\r\n adjustOverflowPadding();\r\n legacyOverflowTimer = window.setTimeout(detectLegacyOverflow, 250);\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Event Handlers\r\n\r\n /**\r\n * Event handler for when one of the close buttons is clicked.\r\n */\r\n function onClose(): void {\r\n emit(\"closeModal\");\r\n internalModalVisible.value = false;\r\n }\r\n\r\n /**\r\n * Event handler for when the scrollable is clicked.\r\n */\r\n function onScrollableClick(): void {\r\n if (props.clickBackdropToClose) {\r\n onClose();\r\n return;\r\n }\r\n\r\n // If we aren't already shaking, start shaking to let the user know\r\n // they are doing something not allowed.\r\n if (!isShaking.value) {\r\n isShaking.value = true;\r\n setTimeout(() => isShaking.value = false, 1000);\r\n }\r\n }\r\n\r\n /**\r\n * Event handler for when the form has been submitted.\r\n */\r\n function onSubmit(): void {\r\n emit(\"save\");\r\n }\r\n\r\n /**\r\n * Event handler for when the visible validation errors have changed.\r\n * This should trigger us showing these errors in the modal.\r\n *\r\n * @param errors The errors that should be displayed.\r\n */\r\n function onVisibleValidationChanged(errors: FormError[]): void {\r\n validationErrors.value = errors;\r\n }\r\n\r\n /**\r\n * Called when the mutation observer has noticed that the DOM inside\r\n * our modal has been modified. Update the resize observer to watch\r\n * those nodes for size changes.\r\n *\r\n * @param mutations The mutations that happened since we were last called.\r\n */\r\n function onOverflowMutation(mutations: MutationRecord[]): void {\r\n for (const mutation of mutations) {\r\n mutation.addedNodes.forEach(node => {\r\n if (node instanceof Element) {\r\n overflowResizeObserver?.observe(node);\r\n }\r\n });\r\n\r\n mutation.removedNodes.forEach(node => {\r\n if (node instanceof Element) {\r\n overflowResizeObserver?.unobserve(node);\r\n }\r\n });\r\n }\r\n\r\n nextTick(adjustOverflowPadding);\r\n }\r\n\r\n /**\r\n * Called when the resize observer has noticed that the size of any child\r\n * nodes have changed. Check if we need to adjust our padding.\r\n */\r\n function onOverflowResize(): void {\r\n adjustOverflowPadding();\r\n }\r\n\r\n // #endregion\r\n\r\n // Watch for changes in our visiblity.\r\n watch(() => props.modelValue, () => {\r\n if (props.modelValue) {\r\n container.value = document.fullscreenElement || document.body;\r\n\r\n // Clear any old validation errors. They will be updated when\r\n // the submit button is next clicked.\r\n validationErrors.value = [];\r\n }\r\n\r\n internalModalVisible.value = props.modelValue;\r\n });\r\n\r\n watch(internalModalVisible, () => {\r\n trackModalState(internalModalVisible.value);\r\n emit(\"update:modelValue\", internalModalVisible.value);\r\n });\r\n\r\n // Watch for changes to the body element reference. When it becomes\r\n // available start observing for changes.\r\n watch(modalBodyElement, () => {\r\n if (overflowMutationObserver && overflowResizeObserver) {\r\n if (modalBodyElement.value) {\r\n overflowMutationObserver.observe(modalBodyElement.value, {\r\n subtree: true,\r\n childList: true\r\n });\r\n\r\n // Start observing initial children.\r\n modalBodyElement.value.querySelectorAll(\"*\").forEach(node => {\r\n if (node instanceof Element) {\r\n overflowResizeObserver.observe(node);\r\n }\r\n });\r\n }\r\n else {\r\n overflowMutationObserver?.disconnect();\r\n overflowResizeObserver?.disconnect();\r\n }\r\n }\r\n else {\r\n if (modalBodyElement.value) {\r\n legacyOverflowTimer = window.setTimeout(detectLegacyOverflow, 250);\r\n }\r\n else if (legacyOverflowTimer) {\r\n clearTimeout(legacyOverflowTimer);\r\n legacyOverflowTimer = undefined;\r\n }\r\n }\r\n });\r\n\r\n onBeforeUnmount(() => {\r\n if (internalModalVisible.value) {\r\n trackModalState(false);\r\n }\r\n\r\n if (overflowMutationObserver && overflowResizeObserver) {\r\n overflowMutationObserver.disconnect();\r\n overflowResizeObserver.disconnect();\r\n }\r\n\r\n if (legacyOverflowTimer) {\r\n clearTimeout(legacyOverflowTimer);\r\n legacyOverflowTimer = undefined;\r\n }\r\n });\r\n\r\n // If we are starting visible, then update the modal tracking.\r\n if (internalModalVisible.value) {\r\n trackModalState(true);\r\n }\r\n</script>\r\n"],"names":["internalModalVisible","ref","props","modelValue","container","_document$fullscreenE","document","fullscreenElement","body","validationErrors","isShaking","modalBodyElement","modalBodyPaddingElement","legacyOverflowTimer","overflowMutationObserver","MutationObserver","onOverflowMutation","undefined","overflowResizeObserver","ResizeObserver","onOverflowResize","adjustOverflowPadding","value","scrollHeight","clientHeight","existingPadding","parseFloat","window","getComputedStyle","getPropertyValue","_unused","totalPadding","style","paddingBottom","concat","detectLegacyOverflow","setTimeout","onClose","emit","onScrollableClick","clickBackdropToClose","onSubmit","onVisibleValidationChanged","errors","mutations","_iterator","_createForOfIteratorHelper","_step","s","n","done","mutation","addedNodes","forEach","node","Element","observe","removedNodes","unobserve","err","e","f","nextTick","watch","trackModalState","subtree","childList","querySelectorAll","disconnect","clearTimeout","onBeforeUnmount"],"mappings":"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"}