Picker.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _vue = require("vue");
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  10. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  11. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  12. var _PickerPanel = _interopRequireDefault(require("./PickerPanel"));
  13. var _PickerTrigger = _interopRequireDefault(require("./PickerTrigger"));
  14. var _dateUtil = require("./utils/dateUtil");
  15. var _miscUtil = _interopRequireWildcard(require("./utils/miscUtil"));
  16. var _PanelContext = require("./PanelContext");
  17. var _uiUtil = require("./utils/uiUtil");
  18. var _usePickerInput3 = _interopRequireDefault(require("./hooks/usePickerInput"));
  19. var _useTextValueMapping3 = _interopRequireDefault(require("./hooks/useTextValueMapping"));
  20. var _useValueTexts3 = _interopRequireDefault(require("./hooks/useValueTexts"));
  21. var _useHoverValue3 = _interopRequireDefault(require("./hooks/useHoverValue"));
  22. var _useMergedState5 = _interopRequireDefault(require("../_util/hooks/useMergedState"));
  23. var _warning = require("../vc-util/warning");
  24. var _classNames4 = _interopRequireDefault(require("../_util/classNames"));
  25. var _context = require("../vc-trigger/context");
  26. var _warnUtil = require("./utils/warnUtil");
  27. function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  28. function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  29. /**
  30. * Removed:
  31. * - getCalendarContainer: use `getPopupContainer` instead
  32. * - onOk
  33. *
  34. * New Feature:
  35. * - picker
  36. * - allowEmpty
  37. * - selectable
  38. *
  39. * Tips: Should add faq about `datetime` mode with `defaultValue`
  40. */
  41. function Picker() {
  42. return (0, _vue.defineComponent)({
  43. name: 'Picker',
  44. inheritAttrs: false,
  45. props: ['prefixCls', 'id', 'tabindex', 'dropdownClassName', 'dropdownAlign', 'popupStyle', 'transitionName', 'generateConfig', 'locale', 'inputReadOnly', 'allowClear', 'autofocus', 'showTime', 'showNow', 'showHour', 'showMinute', 'showSecond', 'picker', 'format', 'use12Hours', 'value', 'defaultValue', 'open', 'defaultOpen', 'defaultOpenValue', 'suffixIcon', 'clearIcon', 'disabled', 'disabledDate', 'placeholder', 'getPopupContainer', 'panelRender', 'inputRender', 'onChange', 'onOpenChange', 'onFocus', 'onBlur', 'onMousedown', 'onMouseup', 'onMouseenter', 'onMouseleave', 'onContextmenu', 'onClick', 'onKeydown', 'onSelect', 'direction', 'autocomplete', 'showToday', 'renderExtraFooter', 'dateRender', 'minuteStep', 'hourStep', 'secondStep', 'hideDisabledOptions'],
  46. // slots: [
  47. // 'suffixIcon',
  48. // 'clearIcon',
  49. // 'prevIcon',
  50. // 'nextIcon',
  51. // 'superPrevIcon',
  52. // 'superNextIcon',
  53. // 'panelRender',
  54. // ],
  55. setup: function setup(props, _ref) {
  56. var attrs = _ref.attrs,
  57. expose = _ref.expose;
  58. var inputRef = (0, _vue.ref)(null);
  59. var picker = (0, _vue.computed)(function () {
  60. var _props$picker;
  61. return (_props$picker = props.picker) !== null && _props$picker !== void 0 ? _props$picker : 'date';
  62. });
  63. var needConfirmButton = (0, _vue.computed)(function () {
  64. return picker.value === 'date' && !!props.showTime || picker.value === 'time';
  65. });
  66. // ============================ Warning ============================
  67. if (process.env.NODE_ENV !== 'production') {
  68. (0, _warnUtil.legacyPropsWarning)(props);
  69. }
  70. // ============================= State =============================
  71. var formatList = (0, _vue.computed)(function () {
  72. return (0, _miscUtil.toArray)((0, _uiUtil.getDefaultFormat)(props.format, picker.value, props.showTime, props.use12Hours));
  73. });
  74. // Panel ref
  75. var panelDivRef = (0, _vue.ref)(null);
  76. var inputDivRef = (0, _vue.ref)(null);
  77. var containerRef = (0, _vue.ref)(null);
  78. // Real value
  79. var _useMergedState = (0, _useMergedState5.default)(null, {
  80. value: (0, _vue.toRef)(props, 'value'),
  81. defaultValue: props.defaultValue
  82. }),
  83. _useMergedState2 = (0, _slicedToArray2.default)(_useMergedState, 2),
  84. mergedValue = _useMergedState2[0],
  85. setInnerValue = _useMergedState2[1];
  86. var selectedValue = (0, _vue.ref)(mergedValue.value);
  87. var setSelectedValue = function setSelectedValue(val) {
  88. selectedValue.value = val;
  89. };
  90. // Operation ref
  91. var operationRef = (0, _vue.ref)(null);
  92. // Open
  93. var _useMergedState3 = (0, _useMergedState5.default)(false, {
  94. value: (0, _vue.toRef)(props, 'open'),
  95. defaultValue: props.defaultOpen,
  96. postState: function postState(postOpen) {
  97. return props.disabled ? false : postOpen;
  98. },
  99. onChange: function onChange(newOpen) {
  100. if (props.onOpenChange) {
  101. props.onOpenChange(newOpen);
  102. }
  103. if (!newOpen && operationRef.value && operationRef.value.onClose) {
  104. operationRef.value.onClose();
  105. }
  106. }
  107. }),
  108. _useMergedState4 = (0, _slicedToArray2.default)(_useMergedState3, 2),
  109. mergedOpen = _useMergedState4[0],
  110. triggerInnerOpen = _useMergedState4[1];
  111. // ============================= Text ==============================
  112. var _useValueTexts = (0, _useValueTexts3.default)(selectedValue, {
  113. formatList: formatList,
  114. generateConfig: (0, _vue.toRef)(props, 'generateConfig'),
  115. locale: (0, _vue.toRef)(props, 'locale')
  116. }),
  117. _useValueTexts2 = (0, _slicedToArray2.default)(_useValueTexts, 2),
  118. valueTexts = _useValueTexts2[0],
  119. firstValueText = _useValueTexts2[1];
  120. var _useTextValueMapping = (0, _useTextValueMapping3.default)({
  121. valueTexts: valueTexts,
  122. onTextChange: function onTextChange(newText) {
  123. var inputDate = (0, _dateUtil.parseValue)(newText, {
  124. locale: props.locale,
  125. formatList: formatList.value,
  126. generateConfig: props.generateConfig
  127. });
  128. if (inputDate && (!props.disabledDate || !props.disabledDate(inputDate))) {
  129. setSelectedValue(inputDate);
  130. }
  131. }
  132. }),
  133. _useTextValueMapping2 = (0, _slicedToArray2.default)(_useTextValueMapping, 3),
  134. text = _useTextValueMapping2[0],
  135. triggerTextChange = _useTextValueMapping2[1],
  136. resetText = _useTextValueMapping2[2];
  137. // ============================ Trigger ============================
  138. var triggerChange = function triggerChange(newValue) {
  139. var onChange = props.onChange,
  140. generateConfig = props.generateConfig,
  141. locale = props.locale;
  142. setSelectedValue(newValue);
  143. setInnerValue(newValue);
  144. if (onChange && !(0, _dateUtil.isEqual)(generateConfig, mergedValue.value, newValue)) {
  145. onChange(newValue, newValue ? (0, _dateUtil.formatValue)(newValue, {
  146. generateConfig: generateConfig,
  147. locale: locale,
  148. format: formatList.value[0]
  149. }) : '');
  150. }
  151. };
  152. var triggerOpen = function triggerOpen(newOpen) {
  153. if (props.disabled && newOpen) {
  154. return;
  155. }
  156. triggerInnerOpen(newOpen);
  157. };
  158. var forwardKeydown = function forwardKeydown(e) {
  159. if (mergedOpen.value && operationRef.value && operationRef.value.onKeydown) {
  160. // Let popup panel handle keyboard
  161. return operationRef.value.onKeydown(e);
  162. }
  163. /* istanbul ignore next */
  164. /* eslint-disable no-lone-blocks */
  165. {
  166. (0, _warning.warning)(false, 'Picker not correct forward Keydown operation. Please help to fire issue about this.');
  167. return false;
  168. }
  169. };
  170. var onInternalMouseup = function onInternalMouseup() {
  171. if (props.onMouseup) {
  172. props.onMouseup.apply(props, arguments);
  173. }
  174. if (inputRef.value) {
  175. inputRef.value.focus();
  176. triggerOpen(true);
  177. }
  178. };
  179. // ============================= Input =============================
  180. var _usePickerInput = (0, _usePickerInput3.default)({
  181. blurToCancel: needConfirmButton,
  182. open: mergedOpen,
  183. value: text,
  184. triggerOpen: triggerOpen,
  185. forwardKeydown: forwardKeydown,
  186. isClickOutside: function isClickOutside(target) {
  187. return !(0, _uiUtil.elementsContains)([panelDivRef.value, inputDivRef.value, containerRef.value], target);
  188. },
  189. onSubmit: function onSubmit() {
  190. if (
  191. // When user typing disabledDate with keyboard and enter, this value will be empty
  192. !selectedValue.value ||
  193. // Normal disabled check
  194. props.disabledDate && props.disabledDate(selectedValue.value)) {
  195. return false;
  196. }
  197. triggerChange(selectedValue.value);
  198. triggerOpen(false);
  199. resetText();
  200. return true;
  201. },
  202. onCancel: function onCancel() {
  203. triggerOpen(false);
  204. setSelectedValue(mergedValue.value);
  205. resetText();
  206. },
  207. onKeydown: function onKeydown(e, preventDefault) {
  208. var _props$onKeydown;
  209. (_props$onKeydown = props.onKeydown) === null || _props$onKeydown === void 0 ? void 0 : _props$onKeydown.call(props, e, preventDefault);
  210. },
  211. onFocus: function onFocus(e) {
  212. var _props$onFocus;
  213. (_props$onFocus = props.onFocus) === null || _props$onFocus === void 0 ? void 0 : _props$onFocus.call(props, e);
  214. },
  215. onBlur: function onBlur(e) {
  216. var _props$onBlur;
  217. (_props$onBlur = props.onBlur) === null || _props$onBlur === void 0 ? void 0 : _props$onBlur.call(props, e);
  218. }
  219. }),
  220. _usePickerInput2 = (0, _slicedToArray2.default)(_usePickerInput, 2),
  221. inputProps = _usePickerInput2[0],
  222. _usePickerInput2$ = _usePickerInput2[1],
  223. focused = _usePickerInput2$.focused,
  224. typing = _usePickerInput2$.typing;
  225. // ============================= Sync ==============================
  226. // Close should sync back with text value
  227. (0, _vue.watch)([mergedOpen, valueTexts], function () {
  228. if (!mergedOpen.value) {
  229. setSelectedValue(mergedValue.value);
  230. if (!valueTexts.value.length || valueTexts.value[0] === '') {
  231. triggerTextChange('');
  232. } else if (firstValueText.value !== text.value) {
  233. resetText();
  234. }
  235. }
  236. });
  237. // Change picker should sync back with text value
  238. (0, _vue.watch)(picker, function () {
  239. if (!mergedOpen.value) {
  240. resetText();
  241. }
  242. });
  243. // Sync innerValue with control mode
  244. (0, _vue.watch)(mergedValue, function () {
  245. // Sync select value
  246. setSelectedValue(mergedValue.value);
  247. });
  248. var _useHoverValue = (0, _useHoverValue3.default)(text, {
  249. formatList: formatList,
  250. generateConfig: (0, _vue.toRef)(props, 'generateConfig'),
  251. locale: (0, _vue.toRef)(props, 'locale')
  252. }),
  253. _useHoverValue2 = (0, _slicedToArray2.default)(_useHoverValue, 3),
  254. hoverValue = _useHoverValue2[0],
  255. onEnter = _useHoverValue2[1],
  256. onLeave = _useHoverValue2[2];
  257. var onContextSelect = function onContextSelect(date, type) {
  258. if (type === 'submit' || type !== 'key' && !needConfirmButton.value) {
  259. // triggerChange will also update selected values
  260. triggerChange(date);
  261. triggerOpen(false);
  262. }
  263. };
  264. (0, _PanelContext.useProvidePanel)({
  265. operationRef: operationRef,
  266. hideHeader: (0, _vue.computed)(function () {
  267. return picker.value === 'time';
  268. }),
  269. panelRef: panelDivRef,
  270. onSelect: onContextSelect,
  271. open: mergedOpen,
  272. defaultOpenValue: (0, _vue.toRef)(props, 'defaultOpenValue'),
  273. onDateMouseenter: onEnter,
  274. onDateMouseleave: onLeave
  275. });
  276. expose({
  277. focus: function focus() {
  278. if (inputRef.value) {
  279. inputRef.value.focus();
  280. }
  281. },
  282. blur: function blur() {
  283. if (inputRef.value) {
  284. inputRef.value.blur();
  285. }
  286. }
  287. });
  288. var getPortal = (0, _context.useProviderTrigger)();
  289. return function () {
  290. var _classNames2;
  291. var _props$prefixCls = props.prefixCls,
  292. prefixCls = _props$prefixCls === void 0 ? 'rc-picker' : _props$prefixCls,
  293. id = props.id,
  294. tabindex = props.tabindex,
  295. dropdownClassName = props.dropdownClassName,
  296. dropdownAlign = props.dropdownAlign,
  297. popupStyle = props.popupStyle,
  298. transitionName = props.transitionName,
  299. generateConfig = props.generateConfig,
  300. locale = props.locale,
  301. inputReadOnly = props.inputReadOnly,
  302. allowClear = props.allowClear,
  303. autofocus = props.autofocus,
  304. _props$picker2 = props.picker,
  305. picker = _props$picker2 === void 0 ? 'date' : _props$picker2,
  306. defaultOpenValue = props.defaultOpenValue,
  307. suffixIcon = props.suffixIcon,
  308. clearIcon = props.clearIcon,
  309. disabled = props.disabled,
  310. placeholder = props.placeholder,
  311. getPopupContainer = props.getPopupContainer,
  312. panelRender = props.panelRender,
  313. onMousedown = props.onMousedown,
  314. onMouseenter = props.onMouseenter,
  315. onMouseleave = props.onMouseleave,
  316. onContextmenu = props.onContextmenu,
  317. onClick = props.onClick,
  318. _onSelect = props.onSelect,
  319. direction = props.direction,
  320. _props$autocomplete = props.autocomplete,
  321. autocomplete = _props$autocomplete === void 0 ? 'off' : _props$autocomplete;
  322. // ============================= Panel =============================
  323. var panelProps = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), attrs), {}, {
  324. class: (0, _classNames4.default)((0, _defineProperty2.default)({}, "".concat(prefixCls, "-panel-focused"), !typing.value)),
  325. style: undefined,
  326. pickerValue: undefined,
  327. onPickerValueChange: undefined,
  328. onChange: null
  329. });
  330. var panelNode = (0, _vue.createVNode)(_PickerPanel.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, panelProps), {}, {
  331. "generateConfig": generateConfig,
  332. "value": selectedValue.value,
  333. "locale": locale,
  334. "tabindex": -1,
  335. "onSelect": function onSelect(date) {
  336. _onSelect === null || _onSelect === void 0 ? void 0 : _onSelect(date);
  337. setSelectedValue(date);
  338. },
  339. "direction": direction,
  340. "onPanelChange": function onPanelChange(viewDate, mode) {
  341. var onPanelChange = props.onPanelChange;
  342. onLeave(true);
  343. onPanelChange === null || onPanelChange === void 0 ? void 0 : onPanelChange(viewDate, mode);
  344. }
  345. }), null);
  346. if (panelRender) {
  347. panelNode = panelRender(panelNode);
  348. }
  349. var panel = (0, _vue.createVNode)("div", {
  350. "class": "".concat(prefixCls, "-panel-container"),
  351. "onMousedown": function onMousedown(e) {
  352. e.preventDefault();
  353. }
  354. }, [panelNode]);
  355. var suffixNode;
  356. if (suffixIcon) {
  357. suffixNode = (0, _vue.createVNode)("span", {
  358. "class": "".concat(prefixCls, "-suffix")
  359. }, [suffixIcon]);
  360. }
  361. var clearNode;
  362. if (allowClear && mergedValue.value && !disabled) {
  363. clearNode = (0, _vue.createVNode)("span", {
  364. "onMousedown": function onMousedown(e) {
  365. e.preventDefault();
  366. e.stopPropagation();
  367. },
  368. "onMouseup": function onMouseup(e) {
  369. e.preventDefault();
  370. e.stopPropagation();
  371. triggerChange(null);
  372. triggerOpen(false);
  373. },
  374. "class": "".concat(prefixCls, "-clear"),
  375. "role": "button"
  376. }, [clearIcon || (0, _vue.createVNode)("span", {
  377. "class": "".concat(prefixCls, "-clear-btn")
  378. }, null)]);
  379. }
  380. var mergedInputProps = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({
  381. id: id,
  382. tabindex: tabindex,
  383. disabled: disabled,
  384. readonly: inputReadOnly || typeof formatList.value[0] === 'function' || !typing.value,
  385. value: hoverValue.value || text.value,
  386. onInput: function onInput(e) {
  387. triggerTextChange(e.target.value);
  388. },
  389. autofocus: autofocus,
  390. placeholder: placeholder,
  391. ref: inputRef,
  392. title: text.value
  393. }, inputProps.value), {}, {
  394. size: (0, _uiUtil.getInputSize)(picker, formatList.value[0], generateConfig)
  395. }, (0, _miscUtil.default)(props)), {}, {
  396. autocomplete: autocomplete
  397. });
  398. var inputNode = props.inputRender ? props.inputRender(mergedInputProps) : (0, _vue.createVNode)("input", mergedInputProps, null);
  399. // ============================ Warning ============================
  400. if (process.env.NODE_ENV !== 'production') {
  401. (0, _warning.warning)(!defaultOpenValue, '`defaultOpenValue` may confuse user for the current value status. Please use `defaultValue` instead.');
  402. }
  403. // ============================ Return =============================
  404. var popupPlacement = direction === 'rtl' ? 'bottomRight' : 'bottomLeft';
  405. return (0, _vue.createVNode)(_PickerTrigger.default, {
  406. "visible": mergedOpen.value,
  407. "popupStyle": popupStyle,
  408. "prefixCls": prefixCls,
  409. "dropdownClassName": dropdownClassName,
  410. "dropdownAlign": dropdownAlign,
  411. "getPopupContainer": getPopupContainer,
  412. "transitionName": transitionName,
  413. "popupPlacement": popupPlacement,
  414. "direction": direction
  415. }, {
  416. default: function _default() {
  417. return [(0, _vue.createVNode)("div", {
  418. "ref": containerRef,
  419. "class": (0, _classNames4.default)(prefixCls, attrs.class, (_classNames2 = {}, (0, _defineProperty2.default)(_classNames2, "".concat(prefixCls, "-disabled"), disabled), (0, _defineProperty2.default)(_classNames2, "".concat(prefixCls, "-focused"), focused.value), (0, _defineProperty2.default)(_classNames2, "".concat(prefixCls, "-rtl"), direction === 'rtl'), _classNames2)),
  420. "style": attrs.style,
  421. "onMousedown": onMousedown,
  422. "onMouseup": onInternalMouseup,
  423. "onMouseenter": onMouseenter,
  424. "onMouseleave": onMouseleave,
  425. "onContextmenu": onContextmenu,
  426. "onClick": onClick
  427. }, [(0, _vue.createVNode)("div", {
  428. "class": (0, _classNames4.default)("".concat(prefixCls, "-input"), (0, _defineProperty2.default)({}, "".concat(prefixCls, "-input-placeholder"), !!hoverValue.value)),
  429. "ref": inputDivRef
  430. }, [inputNode, suffixNode, clearNode]), getPortal()])];
  431. },
  432. popupElement: function popupElement() {
  433. return panel;
  434. }
  435. });
  436. };
  437. }
  438. });
  439. }
  440. var _default2 = Picker();
  441. exports.default = _default2;