UNPKG

vuetify

Version:

Vue Material Component Framework

120 lines (119 loc) 4.09 kB
import { mergeProps as _mergeProps, createVNode as _createVNode } from "vue"; // Styles import "./VDialog.css"; // Components import { VDialogTransition } from "../transitions/index.mjs"; import { VDefaultsProvider } from "../VDefaultsProvider/index.mjs"; import { VOverlay } from "../VOverlay/index.mjs"; // Composables import { useProxiedModel } from "../../composables/proxiedModel.mjs"; import { useScopeId } from "../../composables/scopeId.mjs"; import { forwardRefs } from "../../composables/forwardRefs.mjs"; // Utilities import { computed, mergeProps, nextTick, ref, watch } from 'vue'; import { genericComponent, IN_BROWSER, useRender } from "../../util/index.mjs"; import { filterVOverlayProps, makeVOverlayProps } from "../VOverlay/VOverlay.mjs"; // Types export const VDialog = genericComponent()({ name: 'VDialog', props: { fullscreen: Boolean, retainFocus: { type: Boolean, default: true }, scrollable: Boolean, ...makeVOverlayProps({ origin: 'center center', scrollStrategy: 'block', transition: { component: VDialogTransition }, zIndex: 2400 }) }, emits: { 'update:modelValue': value => true }, setup(props, _ref) { let { slots } = _ref; const isActive = useProxiedModel(props, 'modelValue'); const { scopeId } = useScopeId(); const overlay = ref(); function onFocusin(e) { const before = e.relatedTarget; const after = e.target; if (before !== after && overlay.value?.contentEl && // We're the topmost dialog overlay.value?.globalTop && // It isn't the document or the dialog body ![document, overlay.value.contentEl].includes(after) && // It isn't inside the dialog body !overlay.value.contentEl.contains(after)) { const focusable = [...overlay.value.contentEl.querySelectorAll('button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])')].filter(el => !el.hasAttribute('disabled') && !el.matches('[tabindex="-1"]')); if (!focusable.length) return; const firstElement = focusable[0]; const lastElement = focusable[focusable.length - 1]; if (before === firstElement) { lastElement.focus(); } else { firstElement.focus(); } } } if (IN_BROWSER) { watch(() => isActive.value && props.retainFocus, val => { val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin); }, { immediate: true }); } watch(isActive, async val => { await nextTick(); if (val) { overlay.value.contentEl?.focus({ preventScroll: true }); } else { overlay.value.activatorEl?.focus({ preventScroll: true }); } }); const activatorProps = computed(() => mergeProps({ 'aria-haspopup': 'dialog', 'aria-expanded': String(isActive.value) }, props.activatorProps)); useRender(() => { const [overlayProps] = filterVOverlayProps(props); return _createVNode(VOverlay, _mergeProps({ "ref": overlay, "class": ['v-dialog', { 'v-dialog--fullscreen': props.fullscreen, 'v-dialog--scrollable': props.scrollable }] }, overlayProps, { "modelValue": isActive.value, "onUpdate:modelValue": $event => isActive.value = $event, "aria-role": "dialog", "aria-modal": "true", "activatorProps": activatorProps.value }, scopeId), { activator: slots.activator, default: function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _createVNode(VDefaultsProvider, { "root": true }, { default: () => [slots.default?.(...args)] }); } }); }); return forwardRefs({}, overlay); } }); //# sourceMappingURL=VDialog.mjs.map