Dialog.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
  4. import { defineComponent, onBeforeUnmount, shallowRef, watch, watchEffect } from 'vue';
  5. import contains from '../vc-util/Dom/contains';
  6. import classNames from '../_util/classNames';
  7. import KeyCode from '../_util/KeyCode';
  8. import omit from '../_util/omit';
  9. import pickAttrs from '../_util/pickAttrs';
  10. import { initDefaultProps } from '../_util/props-util';
  11. import Content from './Content';
  12. import dialogPropTypes from './IDialogPropTypes';
  13. import Mask from './Mask';
  14. import { getMotionName, getUUID } from './util';
  15. export default defineComponent({
  16. compatConfig: {
  17. MODE: 3
  18. },
  19. name: 'VcDialog',
  20. inheritAttrs: false,
  21. props: initDefaultProps(_extends(_extends({}, dialogPropTypes()), {
  22. getOpenCount: Function,
  23. scrollLocker: Object
  24. }), {
  25. mask: true,
  26. visible: false,
  27. keyboard: true,
  28. closable: true,
  29. maskClosable: true,
  30. destroyOnClose: false,
  31. prefixCls: 'rc-dialog',
  32. getOpenCount: () => null,
  33. focusTriggerAfterClose: true
  34. }),
  35. setup(props, _ref) {
  36. let {
  37. attrs,
  38. slots
  39. } = _ref;
  40. const lastOutSideActiveElementRef = shallowRef();
  41. const wrapperRef = shallowRef();
  42. const contentRef = shallowRef();
  43. const animatedVisible = shallowRef(props.visible);
  44. const ariaIdRef = shallowRef(`vcDialogTitle${getUUID()}`);
  45. // ========================= Events =========================
  46. const onDialogVisibleChanged = newVisible => {
  47. var _a, _b;
  48. if (newVisible) {
  49. // Try to focus
  50. if (!contains(wrapperRef.value, document.activeElement)) {
  51. lastOutSideActiveElementRef.value = document.activeElement;
  52. (_a = contentRef.value) === null || _a === void 0 ? void 0 : _a.focus();
  53. }
  54. } else {
  55. const preAnimatedVisible = animatedVisible.value;
  56. // Clean up scroll bar & focus back
  57. animatedVisible.value = false;
  58. if (props.mask && lastOutSideActiveElementRef.value && props.focusTriggerAfterClose) {
  59. try {
  60. lastOutSideActiveElementRef.value.focus({
  61. preventScroll: true
  62. });
  63. } catch (e) {
  64. // Do nothing
  65. }
  66. lastOutSideActiveElementRef.value = null;
  67. }
  68. // Trigger afterClose only when change visible from true to false
  69. if (preAnimatedVisible) {
  70. (_b = props.afterClose) === null || _b === void 0 ? void 0 : _b.call(props);
  71. }
  72. }
  73. };
  74. const onInternalClose = e => {
  75. var _a;
  76. (_a = props.onClose) === null || _a === void 0 ? void 0 : _a.call(props, e);
  77. };
  78. // >>> Content
  79. const contentClickRef = shallowRef(false);
  80. const contentTimeoutRef = shallowRef();
  81. // We need record content click incase content popup out of dialog
  82. const onContentMouseDown = () => {
  83. clearTimeout(contentTimeoutRef.value);
  84. contentClickRef.value = true;
  85. };
  86. const onContentMouseUp = () => {
  87. contentTimeoutRef.value = setTimeout(() => {
  88. contentClickRef.value = false;
  89. });
  90. };
  91. const onWrapperClick = e => {
  92. if (!props.maskClosable) return null;
  93. if (contentClickRef.value) {
  94. contentClickRef.value = false;
  95. } else if (wrapperRef.value === e.target) {
  96. onInternalClose(e);
  97. }
  98. };
  99. const onWrapperKeyDown = e => {
  100. if (props.keyboard && e.keyCode === KeyCode.ESC) {
  101. e.stopPropagation();
  102. onInternalClose(e);
  103. return;
  104. }
  105. // keep focus inside dialog
  106. if (props.visible) {
  107. if (e.keyCode === KeyCode.TAB) {
  108. contentRef.value.changeActive(!e.shiftKey);
  109. }
  110. }
  111. };
  112. watch(() => props.visible, () => {
  113. if (props.visible) {
  114. animatedVisible.value = true;
  115. }
  116. }, {
  117. flush: 'post'
  118. });
  119. onBeforeUnmount(() => {
  120. var _a;
  121. clearTimeout(contentTimeoutRef.value);
  122. (_a = props.scrollLocker) === null || _a === void 0 ? void 0 : _a.unLock();
  123. });
  124. watchEffect(() => {
  125. var _a, _b;
  126. (_a = props.scrollLocker) === null || _a === void 0 ? void 0 : _a.unLock();
  127. if (animatedVisible.value) {
  128. (_b = props.scrollLocker) === null || _b === void 0 ? void 0 : _b.lock();
  129. }
  130. });
  131. return () => {
  132. const {
  133. prefixCls,
  134. mask,
  135. visible,
  136. maskTransitionName,
  137. maskAnimation,
  138. zIndex,
  139. wrapClassName,
  140. rootClassName,
  141. wrapStyle,
  142. closable,
  143. maskProps,
  144. maskStyle,
  145. transitionName,
  146. animation,
  147. wrapProps,
  148. title = slots.title
  149. } = props;
  150. const {
  151. style,
  152. class: className
  153. } = attrs;
  154. return _createVNode("div", _objectSpread({
  155. "class": [`${prefixCls}-root`, rootClassName]
  156. }, pickAttrs(props, {
  157. data: true
  158. })), [_createVNode(Mask, {
  159. "prefixCls": prefixCls,
  160. "visible": mask && visible,
  161. "motionName": getMotionName(prefixCls, maskTransitionName, maskAnimation),
  162. "style": _extends({
  163. zIndex
  164. }, maskStyle),
  165. "maskProps": maskProps
  166. }, null), _createVNode("div", _objectSpread({
  167. "tabIndex": -1,
  168. "onKeydown": onWrapperKeyDown,
  169. "class": classNames(`${prefixCls}-wrap`, wrapClassName),
  170. "ref": wrapperRef,
  171. "onClick": onWrapperClick,
  172. "role": "dialog",
  173. "aria-labelledby": title ? ariaIdRef.value : null,
  174. "style": _extends(_extends({
  175. zIndex
  176. }, wrapStyle), {
  177. display: !animatedVisible.value ? 'none' : null
  178. })
  179. }, wrapProps), [_createVNode(Content, _objectSpread(_objectSpread({}, omit(props, ['scrollLocker'])), {}, {
  180. "style": style,
  181. "class": className,
  182. "onMousedown": onContentMouseDown,
  183. "onMouseup": onContentMouseUp,
  184. "ref": contentRef,
  185. "closable": closable,
  186. "ariaId": ariaIdRef.value,
  187. "prefixCls": prefixCls,
  188. "visible": visible,
  189. "onClose": onInternalClose,
  190. "onVisibleChanged": onDialogVisibleChanged,
  191. "motionName": getMotionName(prefixCls, transitionName, animation)
  192. }), slots)])]);
  193. };
  194. }
  195. });