index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  5. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  6. import classNames from 'classnames';
  7. import { useEvent, useMergedState, warning } from 'rc-util';
  8. import * as React from 'react';
  9. import useLocale from "../hooks/useLocale";
  10. import { fillShowTimeConfig, getTimeProps } from "../hooks/useTimeConfig";
  11. import useToggleDates from "../hooks/useToggleDates";
  12. import PickerContext from "../PickerInput/context";
  13. import useCellRender from "../PickerInput/hooks/useCellRender";
  14. import { isSame } from "../utils/dateUtil";
  15. import { pickProps, toArray } from "../utils/miscUtil";
  16. import { PickerHackContext } from "./context";
  17. import DatePanel from "./DatePanel";
  18. import DateTimePanel from "./DateTimePanel";
  19. import DecadePanel from "./DecadePanel";
  20. import MonthPanel from "./MonthPanel";
  21. import QuarterPanel from "./QuarterPanel";
  22. import TimePanel from "./TimePanel";
  23. import WeekPanel from "./WeekPanel";
  24. import YearPanel from "./YearPanel";
  25. var DefaultComponents = {
  26. date: DatePanel,
  27. datetime: DateTimePanel,
  28. week: WeekPanel,
  29. month: MonthPanel,
  30. quarter: QuarterPanel,
  31. year: YearPanel,
  32. decade: DecadePanel,
  33. time: TimePanel
  34. };
  35. function PickerPanel(props, ref) {
  36. var _React$useContext;
  37. var locale = props.locale,
  38. generateConfig = props.generateConfig,
  39. direction = props.direction,
  40. prefixCls = props.prefixCls,
  41. _props$tabIndex = props.tabIndex,
  42. tabIndex = _props$tabIndex === void 0 ? 0 : _props$tabIndex,
  43. multiple = props.multiple,
  44. defaultValue = props.defaultValue,
  45. value = props.value,
  46. onChange = props.onChange,
  47. onSelect = props.onSelect,
  48. defaultPickerValue = props.defaultPickerValue,
  49. pickerValue = props.pickerValue,
  50. onPickerValueChange = props.onPickerValueChange,
  51. mode = props.mode,
  52. onPanelChange = props.onPanelChange,
  53. _props$picker = props.picker,
  54. picker = _props$picker === void 0 ? 'date' : _props$picker,
  55. showTime = props.showTime,
  56. hoverValue = props.hoverValue,
  57. hoverRangeValue = props.hoverRangeValue,
  58. cellRender = props.cellRender,
  59. dateRender = props.dateRender,
  60. monthCellRender = props.monthCellRender,
  61. _props$components = props.components,
  62. components = _props$components === void 0 ? {} : _props$components,
  63. hideHeader = props.hideHeader;
  64. var mergedPrefixCls = ((_React$useContext = React.useContext(PickerContext)) === null || _React$useContext === void 0 ? void 0 : _React$useContext.prefixCls) || prefixCls || 'rc-picker';
  65. // ========================== Refs ==========================
  66. var rootRef = React.useRef();
  67. React.useImperativeHandle(ref, function () {
  68. return {
  69. nativeElement: rootRef.current
  70. };
  71. });
  72. // ========================== Time ==========================
  73. // Auto `format` need to check `showTime.showXXX` first.
  74. // And then merge the `locale` into `mergedShowTime`.
  75. var _getTimeProps = getTimeProps(props),
  76. _getTimeProps2 = _slicedToArray(_getTimeProps, 4),
  77. timeProps = _getTimeProps2[0],
  78. localeTimeProps = _getTimeProps2[1],
  79. showTimeFormat = _getTimeProps2[2],
  80. propFormat = _getTimeProps2[3];
  81. // ========================= Locale =========================
  82. var filledLocale = useLocale(locale, localeTimeProps);
  83. // ========================= Picker =========================
  84. var internalPicker = picker === 'date' && showTime ? 'datetime' : picker;
  85. // ======================== ShowTime ========================
  86. var mergedShowTime = React.useMemo(function () {
  87. return fillShowTimeConfig(internalPicker, showTimeFormat, propFormat, timeProps, filledLocale);
  88. }, [internalPicker, showTimeFormat, propFormat, timeProps, filledLocale]);
  89. // ========================== Now ===========================
  90. var now = generateConfig.getNow();
  91. // ========================== Mode ==========================
  92. var _useMergedState = useMergedState(picker, {
  93. value: mode,
  94. postState: function postState(val) {
  95. return val || 'date';
  96. }
  97. }),
  98. _useMergedState2 = _slicedToArray(_useMergedState, 2),
  99. mergedMode = _useMergedState2[0],
  100. setMergedMode = _useMergedState2[1];
  101. var internalMode = mergedMode === 'date' && mergedShowTime ? 'datetime' : mergedMode;
  102. // ========================= Toggle =========================
  103. var toggleDates = useToggleDates(generateConfig, locale, internalPicker);
  104. // ========================= Value ==========================
  105. // >>> Real value
  106. // Interactive with `onChange` event which only trigger when the `mode` is `picker`
  107. var _useMergedState3 = useMergedState(defaultValue, {
  108. value: value
  109. }),
  110. _useMergedState4 = _slicedToArray(_useMergedState3, 2),
  111. innerValue = _useMergedState4[0],
  112. setMergedValue = _useMergedState4[1];
  113. var mergedValue = React.useMemo(function () {
  114. // Clean up `[null]`
  115. var values = toArray(innerValue).filter(function (val) {
  116. return val;
  117. });
  118. return multiple ? values : values.slice(0, 1);
  119. }, [innerValue, multiple]);
  120. // Sync value and only trigger onChange event when changed
  121. var triggerChange = useEvent(function (nextValue) {
  122. setMergedValue(nextValue);
  123. if (onChange && (nextValue === null || mergedValue.length !== nextValue.length || mergedValue.some(function (ori, index) {
  124. return !isSame(generateConfig, locale, ori, nextValue[index], internalPicker);
  125. }))) {
  126. onChange === null || onChange === void 0 || onChange(multiple ? nextValue : nextValue[0]);
  127. }
  128. });
  129. // >>> CalendarValue
  130. // CalendarValue is a temp value for user operation
  131. // which will only trigger `onCalendarChange` but not `onChange`
  132. var onInternalSelect = useEvent(function (newDate) {
  133. onSelect === null || onSelect === void 0 || onSelect(newDate);
  134. if (mergedMode === picker) {
  135. var nextValues = multiple ? toggleDates(mergedValue, newDate) : [newDate];
  136. triggerChange(nextValues);
  137. }
  138. });
  139. // >>> PickerValue
  140. // PickerValue is used to control the current displaying panel
  141. var _useMergedState5 = useMergedState(defaultPickerValue || mergedValue[0] || now, {
  142. value: pickerValue
  143. }),
  144. _useMergedState6 = _slicedToArray(_useMergedState5, 2),
  145. mergedPickerValue = _useMergedState6[0],
  146. setInternalPickerValue = _useMergedState6[1];
  147. React.useEffect(function () {
  148. if (mergedValue[0] && !pickerValue) {
  149. setInternalPickerValue(mergedValue[0]);
  150. }
  151. }, [mergedValue[0]]);
  152. // Both trigger when manually pickerValue or mode change
  153. var triggerPanelChange = function triggerPanelChange(viewDate, nextMode) {
  154. onPanelChange === null || onPanelChange === void 0 || onPanelChange(viewDate || pickerValue, nextMode || mergedMode);
  155. };
  156. var setPickerValue = function setPickerValue(nextPickerValue) {
  157. var triggerPanelEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  158. setInternalPickerValue(nextPickerValue);
  159. onPickerValueChange === null || onPickerValueChange === void 0 || onPickerValueChange(nextPickerValue);
  160. if (triggerPanelEvent) {
  161. triggerPanelChange(nextPickerValue);
  162. }
  163. };
  164. var triggerModeChange = function triggerModeChange(nextMode, viewDate) {
  165. setMergedMode(nextMode);
  166. if (viewDate) {
  167. setPickerValue(viewDate);
  168. }
  169. triggerPanelChange(viewDate, nextMode);
  170. };
  171. var onPanelValueSelect = function onPanelValueSelect(nextValue) {
  172. onInternalSelect(nextValue);
  173. setPickerValue(nextValue);
  174. // Update mode if needed
  175. if (mergedMode !== picker) {
  176. var decadeYearQueue = ['decade', 'year'];
  177. var decadeYearMonthQueue = [].concat(decadeYearQueue, ['month']);
  178. var pickerQueue = {
  179. quarter: [].concat(decadeYearQueue, ['quarter']),
  180. week: [].concat(_toConsumableArray(decadeYearMonthQueue), ['week']),
  181. date: [].concat(_toConsumableArray(decadeYearMonthQueue), ['date'])
  182. };
  183. var queue = pickerQueue[picker] || decadeYearMonthQueue;
  184. var index = queue.indexOf(mergedMode);
  185. var nextMode = queue[index + 1];
  186. if (nextMode) {
  187. triggerModeChange(nextMode, nextValue);
  188. }
  189. }
  190. };
  191. // ======================= Hover Date =======================
  192. var hoverRangeDate = React.useMemo(function () {
  193. var start;
  194. var end;
  195. if (Array.isArray(hoverRangeValue)) {
  196. var _hoverRangeValue = _slicedToArray(hoverRangeValue, 2);
  197. start = _hoverRangeValue[0];
  198. end = _hoverRangeValue[1];
  199. } else {
  200. start = hoverRangeValue;
  201. }
  202. // Return for not exist
  203. if (!start && !end) {
  204. return null;
  205. }
  206. // Fill if has empty
  207. start = start || end;
  208. end = end || start;
  209. return generateConfig.isAfter(start, end) ? [end, start] : [start, end];
  210. }, [hoverRangeValue, generateConfig]);
  211. // ======================= Components =======================
  212. // >>> cellRender
  213. var onInternalCellRender = useCellRender(cellRender, dateRender, monthCellRender);
  214. // ======================= Components =======================
  215. var PanelComponent = components[internalMode] || DefaultComponents[internalMode] || DatePanel;
  216. // ======================== Context =========================
  217. var parentHackContext = React.useContext(PickerHackContext);
  218. var pickerPanelContext = React.useMemo(function () {
  219. return _objectSpread(_objectSpread({}, parentHackContext), {}, {
  220. hideHeader: hideHeader
  221. });
  222. }, [parentHackContext, hideHeader]);
  223. // ======================== Warnings ========================
  224. if (process.env.NODE_ENV !== 'production') {
  225. warning(!mergedValue || mergedValue.every(function (val) {
  226. return generateConfig.isValidate(val);
  227. }), 'Invalidate date pass to `value` or `defaultValue`.');
  228. }
  229. // ========================= Render =========================
  230. var panelCls = "".concat(mergedPrefixCls, "-panel");
  231. var panelProps = pickProps(props, [
  232. // Week
  233. 'showWeek',
  234. // Icons
  235. 'prevIcon', 'nextIcon', 'superPrevIcon', 'superNextIcon',
  236. // Disabled
  237. 'disabledDate', 'minDate', 'maxDate',
  238. // Hover
  239. 'onHover']);
  240. return /*#__PURE__*/React.createElement(PickerHackContext.Provider, {
  241. value: pickerPanelContext
  242. }, /*#__PURE__*/React.createElement("div", {
  243. ref: rootRef,
  244. tabIndex: tabIndex,
  245. className: classNames(panelCls, _defineProperty({}, "".concat(panelCls, "-rtl"), direction === 'rtl'))
  246. }, /*#__PURE__*/React.createElement(PanelComponent, _extends({}, panelProps, {
  247. // Time
  248. showTime: mergedShowTime
  249. // MISC
  250. ,
  251. prefixCls: mergedPrefixCls,
  252. locale: filledLocale,
  253. generateConfig: generateConfig
  254. // Mode
  255. ,
  256. onModeChange: triggerModeChange
  257. // Value
  258. ,
  259. pickerValue: mergedPickerValue,
  260. onPickerValueChange: function onPickerValueChange(nextPickerValue) {
  261. setPickerValue(nextPickerValue, true);
  262. },
  263. value: mergedValue[0],
  264. onSelect: onPanelValueSelect,
  265. values: mergedValue
  266. // Render
  267. ,
  268. cellRender: onInternalCellRender
  269. // Hover
  270. ,
  271. hoverRangeValue: hoverRangeDate,
  272. hoverValue: hoverValue
  273. }))));
  274. }
  275. var RefPanelPicker = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef(PickerPanel));
  276. if (process.env.NODE_ENV !== 'production') {
  277. RefPanelPicker.displayName = 'PanelPicker';
  278. }
  279. // Make support generic
  280. export default RefPanelPicker;