usePickerInput.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.default = usePickerInput;
  7. var _vue = require("vue");
  8. var _KeyCode = _interopRequireDefault(require("../../_util/KeyCode"));
  9. var _uiUtil = require("../utils/uiUtil");
  10. var _raf = _interopRequireDefault(require("../../_util/raf"));
  11. function usePickerInput(_ref) {
  12. let {
  13. open,
  14. value,
  15. isClickOutside,
  16. triggerOpen,
  17. forwardKeydown,
  18. onKeydown,
  19. blurToCancel,
  20. onSubmit,
  21. onCancel,
  22. onFocus,
  23. onBlur
  24. } = _ref;
  25. const typing = (0, _vue.shallowRef)(false);
  26. const focused = (0, _vue.shallowRef)(false);
  27. /**
  28. * We will prevent blur to handle open event when user click outside,
  29. * since this will repeat trigger `onOpenChange` event.
  30. */
  31. const preventBlurRef = (0, _vue.shallowRef)(false);
  32. const valueChangedRef = (0, _vue.shallowRef)(false);
  33. const preventDefaultRef = (0, _vue.shallowRef)(false);
  34. const inputProps = (0, _vue.computed)(() => ({
  35. onMousedown: () => {
  36. typing.value = true;
  37. triggerOpen(true);
  38. },
  39. onKeydown: e => {
  40. const preventDefault = () => {
  41. preventDefaultRef.value = true;
  42. };
  43. onKeydown(e, preventDefault);
  44. if (preventDefaultRef.value) return;
  45. switch (e.which) {
  46. case _KeyCode.default.ENTER:
  47. {
  48. if (!open.value) {
  49. triggerOpen(true);
  50. } else if (onSubmit() !== false) {
  51. typing.value = true;
  52. }
  53. e.preventDefault();
  54. return;
  55. }
  56. case _KeyCode.default.TAB:
  57. {
  58. if (typing.value && open.value && !e.shiftKey) {
  59. typing.value = false;
  60. e.preventDefault();
  61. } else if (!typing.value && open.value) {
  62. if (!forwardKeydown(e) && e.shiftKey) {
  63. typing.value = true;
  64. e.preventDefault();
  65. }
  66. }
  67. return;
  68. }
  69. case _KeyCode.default.ESC:
  70. {
  71. typing.value = true;
  72. onCancel();
  73. return;
  74. }
  75. }
  76. if (!open.value && ![_KeyCode.default.SHIFT].includes(e.which)) {
  77. triggerOpen(true);
  78. } else if (!typing.value) {
  79. // Let popup panel handle keyboard
  80. forwardKeydown(e);
  81. }
  82. },
  83. onFocus: e => {
  84. typing.value = true;
  85. focused.value = true;
  86. if (onFocus) {
  87. onFocus(e);
  88. }
  89. },
  90. onBlur: e => {
  91. if (preventBlurRef.value || !isClickOutside(document.activeElement)) {
  92. preventBlurRef.value = false;
  93. return;
  94. }
  95. if (blurToCancel.value) {
  96. setTimeout(() => {
  97. let {
  98. activeElement
  99. } = document;
  100. while (activeElement && activeElement.shadowRoot) {
  101. activeElement = activeElement.shadowRoot.activeElement;
  102. }
  103. if (isClickOutside(activeElement)) {
  104. onCancel();
  105. }
  106. }, 0);
  107. } else if (open.value) {
  108. triggerOpen(false);
  109. if (valueChangedRef.value) {
  110. onSubmit();
  111. }
  112. }
  113. focused.value = false;
  114. if (onBlur) {
  115. onBlur(e);
  116. }
  117. }
  118. }));
  119. // check if value changed
  120. (0, _vue.watch)(open, () => {
  121. valueChangedRef.value = false;
  122. });
  123. (0, _vue.watch)(value, () => {
  124. valueChangedRef.value = true;
  125. });
  126. const globalMousedownEvent = (0, _vue.shallowRef)();
  127. // Global click handler
  128. (0, _vue.onMounted)(() => {
  129. globalMousedownEvent.value = (0, _uiUtil.addGlobalMousedownEvent)(e => {
  130. const target = (0, _uiUtil.getTargetFromEvent)(e);
  131. if (open.value) {
  132. const clickedOutside = isClickOutside(target);
  133. if (!clickedOutside) {
  134. preventBlurRef.value = true;
  135. // Always set back in case `onBlur` prevented by user
  136. (0, _raf.default)(() => {
  137. preventBlurRef.value = false;
  138. });
  139. } else if (!focused.value || clickedOutside) {
  140. triggerOpen(false);
  141. }
  142. }
  143. });
  144. });
  145. (0, _vue.onBeforeUnmount)(() => {
  146. globalMousedownEvent.value && globalMousedownEvent.value();
  147. });
  148. return [inputProps, {
  149. focused,
  150. typing
  151. }];
  152. }