149 lines
4.3 KiB
JavaScript
149 lines
4.3 KiB
JavaScript
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
||
|
import KeyCode from "rc-util/es/KeyCode";
|
||
|
import raf from "rc-util/es/raf";
|
||
|
import { useEffect, useRef, useState } from 'react';
|
||
|
import { addGlobalMouseDownEvent, getTargetFromEvent } from "../utils/uiUtil";
|
||
|
export default function usePickerInput(_ref) {
|
||
|
var open = _ref.open,
|
||
|
value = _ref.value,
|
||
|
isClickOutside = _ref.isClickOutside,
|
||
|
triggerOpen = _ref.triggerOpen,
|
||
|
forwardKeyDown = _ref.forwardKeyDown,
|
||
|
_onKeyDown = _ref.onKeyDown,
|
||
|
blurToCancel = _ref.blurToCancel,
|
||
|
changeOnBlur = _ref.changeOnBlur,
|
||
|
onSubmit = _ref.onSubmit,
|
||
|
onCancel = _ref.onCancel,
|
||
|
_onFocus = _ref.onFocus,
|
||
|
_onBlur = _ref.onBlur;
|
||
|
var _useState = useState(false),
|
||
|
_useState2 = _slicedToArray(_useState, 2),
|
||
|
typing = _useState2[0],
|
||
|
setTyping = _useState2[1];
|
||
|
var _useState3 = useState(false),
|
||
|
_useState4 = _slicedToArray(_useState3, 2),
|
||
|
focused = _useState4[0],
|
||
|
setFocused = _useState4[1];
|
||
|
|
||
|
/**
|
||
|
* We will prevent blur to handle open event when user click outside,
|
||
|
* since this will repeat trigger `onOpenChange` event.
|
||
|
*/
|
||
|
var preventBlurRef = useRef(false);
|
||
|
var valueChangedRef = useRef(false);
|
||
|
var preventDefaultRef = useRef(false);
|
||
|
var inputProps = {
|
||
|
onMouseDown: function onMouseDown() {
|
||
|
setTyping(true);
|
||
|
triggerOpen(true);
|
||
|
},
|
||
|
onKeyDown: function onKeyDown(e) {
|
||
|
var preventDefault = function preventDefault() {
|
||
|
preventDefaultRef.current = true;
|
||
|
};
|
||
|
_onKeyDown(e, preventDefault);
|
||
|
if (preventDefaultRef.current) return;
|
||
|
switch (e.which) {
|
||
|
case KeyCode.ENTER:
|
||
|
{
|
||
|
if (!open) {
|
||
|
triggerOpen(true);
|
||
|
} else if (onSubmit() !== false) {
|
||
|
setTyping(true);
|
||
|
}
|
||
|
e.preventDefault();
|
||
|
return;
|
||
|
}
|
||
|
case KeyCode.TAB:
|
||
|
{
|
||
|
if (typing && open && !e.shiftKey) {
|
||
|
setTyping(false);
|
||
|
e.preventDefault();
|
||
|
} else if (!typing && open) {
|
||
|
if (!forwardKeyDown(e) && e.shiftKey) {
|
||
|
setTyping(true);
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
case KeyCode.ESC:
|
||
|
{
|
||
|
setTyping(true);
|
||
|
onCancel();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
if (!open && ![KeyCode.SHIFT].includes(e.which)) {
|
||
|
triggerOpen(true);
|
||
|
} else if (!typing) {
|
||
|
// Let popup panel handle keyboard
|
||
|
forwardKeyDown(e);
|
||
|
}
|
||
|
},
|
||
|
onFocus: function onFocus(e) {
|
||
|
setTyping(true);
|
||
|
setFocused(true);
|
||
|
if (_onFocus) {
|
||
|
_onFocus(e);
|
||
|
}
|
||
|
},
|
||
|
onBlur: function onBlur(e) {
|
||
|
if (preventBlurRef.current || !isClickOutside(document.activeElement)) {
|
||
|
preventBlurRef.current = false;
|
||
|
return;
|
||
|
}
|
||
|
if (blurToCancel) {
|
||
|
setTimeout(function () {
|
||
|
var _document = document,
|
||
|
activeElement = _document.activeElement;
|
||
|
while (activeElement && activeElement.shadowRoot) {
|
||
|
activeElement = activeElement.shadowRoot.activeElement;
|
||
|
}
|
||
|
if (isClickOutside(activeElement)) {
|
||
|
onCancel();
|
||
|
}
|
||
|
}, 0);
|
||
|
} else if (open) {
|
||
|
triggerOpen(false);
|
||
|
if (valueChangedRef.current) {
|
||
|
onSubmit();
|
||
|
}
|
||
|
}
|
||
|
setFocused(false);
|
||
|
_onBlur === null || _onBlur === void 0 ? void 0 : _onBlur(e);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// check if value changed
|
||
|
useEffect(function () {
|
||
|
valueChangedRef.current = false;
|
||
|
}, [open]);
|
||
|
useEffect(function () {
|
||
|
valueChangedRef.current = true;
|
||
|
}, [value]);
|
||
|
|
||
|
// Global click handler
|
||
|
useEffect(function () {
|
||
|
return addGlobalMouseDownEvent(function (e) {
|
||
|
var target = getTargetFromEvent(e);
|
||
|
var clickedOutside = isClickOutside(target);
|
||
|
if (open) {
|
||
|
if (!clickedOutside) {
|
||
|
preventBlurRef.current = true;
|
||
|
|
||
|
// Always set back in case `onBlur` prevented by user
|
||
|
raf(function () {
|
||
|
preventBlurRef.current = false;
|
||
|
});
|
||
|
} else if (!changeOnBlur && !blurToCancel && (!focused || clickedOutside)) {
|
||
|
triggerOpen(false);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
return [inputProps, {
|
||
|
focused: focused,
|
||
|
typing: typing
|
||
|
}];
|
||
|
}
|