123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- 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";
- import { makeVOverlayProps } from "../VOverlay/VOverlay.mjs"; // Composables
- import { forwardRefs } from "../../composables/forwardRefs.mjs";
- import { useProxiedModel } from "../../composables/proxiedModel.mjs";
- import { useScopeId } from "../../composables/scopeId.mjs"; // Utilities
- import { mergeProps, nextTick, onBeforeUnmount, ref, watch } from 'vue';
- import { focusableChildren, genericComponent, IN_BROWSER, propsFactory, useRender } from "../../util/index.mjs"; // Types
- export const makeVDialogProps = propsFactory({
- fullscreen: Boolean,
- retainFocus: {
- type: Boolean,
- default: true
- },
- scrollable: Boolean,
- ...makeVOverlayProps({
- origin: 'center center',
- scrollStrategy: 'block',
- transition: {
- component: VDialogTransition
- },
- zIndex: 2400
- })
- }, 'VDialog');
- export const VDialog = genericComponent()({
- name: 'VDialog',
- props: makeVDialogProps(),
- emits: {
- 'update:modelValue': value => true,
- afterEnter: () => true,
- afterLeave: () => true
- },
- setup(props, _ref) {
- let {
- emit,
- 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 = focusableChildren(overlay.value.contentEl);
- if (!focusable.length) return;
- const firstElement = focusable[0];
- const lastElement = focusable[focusable.length - 1];
- if (before === firstElement) {
- lastElement.focus();
- } else {
- firstElement.focus();
- }
- }
- }
- onBeforeUnmount(() => {
- document.removeEventListener('focusin', onFocusin);
- });
- if (IN_BROWSER) {
- watch(() => isActive.value && props.retainFocus, val => {
- val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin);
- }, {
- immediate: true
- });
- }
- function onAfterEnter() {
- emit('afterEnter');
- if (overlay.value?.contentEl && !overlay.value.contentEl.contains(document.activeElement)) {
- overlay.value.contentEl.focus({
- preventScroll: true
- });
- }
- }
- function onAfterLeave() {
- emit('afterLeave');
- }
- watch(isActive, async val => {
- if (!val) {
- await nextTick();
- overlay.value.activatorEl?.focus({
- preventScroll: true
- });
- }
- });
- useRender(() => {
- const overlayProps = VOverlay.filterProps(props);
- const activatorProps = mergeProps({
- 'aria-haspopup': 'dialog'
- }, props.activatorProps);
- const contentProps = mergeProps({
- tabindex: -1
- }, props.contentProps);
- return _createVNode(VOverlay, _mergeProps({
- "ref": overlay,
- "class": ['v-dialog', {
- 'v-dialog--fullscreen': props.fullscreen,
- 'v-dialog--scrollable': props.scrollable
- }, props.class],
- "style": props.style
- }, overlayProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "aria-modal": "true",
- "activatorProps": activatorProps,
- "contentProps": contentProps,
- "height": !props.fullscreen ? props.height : undefined,
- "width": !props.fullscreen ? props.width : undefined,
- "maxHeight": !props.fullscreen ? props.maxHeight : undefined,
- "maxWidth": !props.fullscreen ? props.maxWidth : undefined,
- "role": "dialog",
- "onAfterEnter": onAfterEnter,
- "onAfterLeave": onAfterLeave
- }, 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": "VDialog"
- }, {
- default: () => [slots.default?.(...args)]
- });
- }
- });
- });
- return forwardRefs({}, overlay);
- }
- });
- //# sourceMappingURL=VDialog.mjs.map
|