refactor: date
parent
a020c2f681
commit
a8113d7c55
|
@ -381,7 +381,7 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
|
||||||
<PickerPanel<DateType>
|
<PickerPanel<DateType>
|
||||||
{...panelProps}
|
{...panelProps}
|
||||||
generateConfig={generateConfig}
|
generateConfig={generateConfig}
|
||||||
className={classNames({
|
class={classNames({
|
||||||
[`${prefixCls}-panel-focused`]: !typing,
|
[`${prefixCls}-panel-focused`]: !typing,
|
||||||
})}
|
})}
|
||||||
value={selectedValue}
|
value={selectedValue}
|
||||||
|
@ -406,8 +406,8 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
|
||||||
|
|
||||||
const panel = (
|
const panel = (
|
||||||
<div
|
<div
|
||||||
className={`${prefixCls}-panel-container`}
|
class={`${prefixCls}-panel-container`}
|
||||||
onMouseDown={(e) => {
|
onMousedown={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -417,27 +417,27 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
|
||||||
|
|
||||||
let suffixNode: React.ReactNode;
|
let suffixNode: React.ReactNode;
|
||||||
if (suffixIcon) {
|
if (suffixIcon) {
|
||||||
suffixNode = <span className={`${prefixCls}-suffix`}>{suffixIcon}</span>;
|
suffixNode = <span class={`${prefixCls}-suffix`}>{suffixIcon}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clearNode: React.ReactNode;
|
let clearNode: React.ReactNode;
|
||||||
if (allowClear && mergedValue && !disabled) {
|
if (allowClear && mergedValue && !disabled) {
|
||||||
clearNode = (
|
clearNode = (
|
||||||
<span
|
<span
|
||||||
onMouseDown={(e) => {
|
onMousedown={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
onMouseUp={(e) => {
|
onMouseup={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
triggerChange(null);
|
triggerChange(null);
|
||||||
triggerOpen(false);
|
triggerOpen(false);
|
||||||
}}
|
}}
|
||||||
className={`${prefixCls}-clear`}
|
class={`${prefixCls}-clear`}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
{clearIcon || <span className={`${prefixCls}-clear-btn`} />}
|
{clearIcon || <span class={`${prefixCls}-clear-btn`} />}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -486,21 +486,21 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
|
||||||
direction={direction}
|
direction={direction}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(prefixCls, className, {
|
class={classNames(prefixCls, className, {
|
||||||
[`${prefixCls}-disabled`]: disabled,
|
[`${prefixCls}-disabled`]: disabled,
|
||||||
[`${prefixCls}-focused`]: focused,
|
[`${prefixCls}-focused`]: focused,
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
})}
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
onMouseDown={onMouseDown}
|
onMousedown={onMouseDown}
|
||||||
onMouseUp={onInternalMouseUp}
|
onMouseup={onInternalMouseUp}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseenter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseleave={onMouseLeave}
|
||||||
onContextMenu={onContextMenu}
|
onContextmenu={onContextMenu}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(`${prefixCls}-input`, {
|
class={classNames(`${prefixCls}-input`, {
|
||||||
[`${prefixCls}-input-placeholder`]: !!hoverValue,
|
[`${prefixCls}-input-placeholder`]: !!hoverValue,
|
||||||
})}
|
})}
|
||||||
ref={inputDivRef}
|
ref={inputDivRef}
|
||||||
|
@ -509,19 +509,19 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
|
||||||
id={id}
|
id={id}
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
readOnly={inputReadOnly || typeof formatList[0] === 'function' || !typing}
|
readonly={inputReadOnly || typeof formatList[0] === 'function' || !typing}
|
||||||
value={hoverValue || text}
|
value={hoverValue || text}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
triggerTextChange(e.target.value);
|
triggerTextChange(e.target.value);
|
||||||
}}
|
}}
|
||||||
autoFocus={autoFocus}
|
autofocus={autoFocus}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
title={text}
|
title={text}
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
size={getInputSize(picker, formatList[0], generateConfig)}
|
size={getInputSize(picker, formatList[0], generateConfig)}
|
||||||
{...getDataOrAriaProps(props)}
|
{...getDataOrAriaProps(props)}
|
||||||
autoComplete={autoComplete}
|
autocomplete={autoComplete}
|
||||||
/>
|
/>
|
||||||
{suffixNode}
|
{suffixNode}
|
||||||
{clearNode}
|
{clearNode}
|
||||||
|
|
|
@ -515,7 +515,7 @@ function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
|
||||||
const disabled = disabledDate && disabledDate(now);
|
const disabled = disabledDate && disabledDate(now);
|
||||||
todayNode = (
|
todayNode = (
|
||||||
<a
|
<a
|
||||||
className={classNames(todayCls, disabled && `${todayCls}-disabled`)}
|
class={classNames(todayCls, disabled && `${todayCls}-disabled`)}
|
||||||
aria-disabled={disabled}
|
aria-disabled={disabled}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
|
@ -539,22 +539,22 @@ function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
tabIndex={tabIndex}
|
tabindex={tabIndex}
|
||||||
className={classNames(`${prefixCls}-panel`, className, {
|
class={classNames(`${prefixCls}-panel`, className, {
|
||||||
[`${prefixCls}-panel-has-range`]: rangedValue && rangedValue[0] && rangedValue[1],
|
[`${prefixCls}-panel-has-range`]: rangedValue && rangedValue[0] && rangedValue[1],
|
||||||
[`${prefixCls}-panel-has-range-hover`]:
|
[`${prefixCls}-panel-has-range-hover`]:
|
||||||
hoverRangedValue && hoverRangedValue[0] && hoverRangedValue[1],
|
hoverRangedValue && hoverRangedValue[0] && hoverRangedValue[1],
|
||||||
[`${prefixCls}-panel-rtl`]: direction === 'rtl',
|
[`${prefixCls}-panel-rtl`]: direction === 'rtl',
|
||||||
})}
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
onKeyDown={onInternalKeyDown}
|
onKeydown={onInternalKeyDown}
|
||||||
onBlur={onInternalBlur}
|
onBlur={onInternalBlur}
|
||||||
onMouseDown={onMouseDown}
|
onMousedown={onMouseDown}
|
||||||
ref={panelDivRef}
|
ref={panelDivRef}
|
||||||
>
|
>
|
||||||
{panelNode}
|
{panelNode}
|
||||||
{extraFooter || rangesNode || todayNode ? (
|
{extraFooter || rangesNode || todayNode ? (
|
||||||
<div className={`${prefixCls}-footer`}>
|
<div class={`${prefixCls}-footer`}>
|
||||||
{extraFooter}
|
{extraFooter}
|
||||||
{rangesNode}
|
{rangesNode}
|
||||||
{todayNode}
|
{todayNode}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import * as React from 'react';
|
import { CSSProperties } from '@vue/runtime-dom';
|
||||||
import classNames from 'classnames';
|
import { AlignType } from '../vc-align/interface';
|
||||||
import Trigger from 'rc-trigger';
|
import Trigger from '../vc-trigger';
|
||||||
import type { AlignType } from 'rc-trigger/lib/interface';
|
import classNames from '../_util/classNames';
|
||||||
|
import { VueNode } from '../_util/type';
|
||||||
|
|
||||||
const BUILT_IN_PLACEMENTS = {
|
const BUILT_IN_PLACEMENTS = {
|
||||||
bottomLeft: {
|
bottomLeft: {
|
||||||
|
@ -43,9 +44,9 @@ type Placement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
|
||||||
export type PickerTriggerProps = {
|
export type PickerTriggerProps = {
|
||||||
prefixCls: string;
|
prefixCls: string;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
popupElement: React.ReactElement;
|
popupElement: VueNode;
|
||||||
popupStyle?: React.CSSProperties;
|
popupStyle?: CSSProperties;
|
||||||
children: React.ReactElement;
|
children: VueNode;
|
||||||
dropdownClassName?: string;
|
dropdownClassName?: string;
|
||||||
transitionName?: string;
|
transitionName?: string;
|
||||||
getPopupContainer?: (node: HTMLElement) => HTMLElement;
|
getPopupContainer?: (node: HTMLElement) => HTMLElement;
|
||||||
|
@ -55,20 +56,22 @@ export type PickerTriggerProps = {
|
||||||
direction?: 'ltr' | 'rtl';
|
direction?: 'ltr' | 'rtl';
|
||||||
};
|
};
|
||||||
|
|
||||||
function PickerTrigger({
|
function PickerTrigger(
|
||||||
prefixCls,
|
{
|
||||||
popupElement,
|
prefixCls,
|
||||||
popupStyle,
|
popupElement,
|
||||||
visible,
|
popupStyle,
|
||||||
dropdownClassName,
|
visible,
|
||||||
dropdownAlign,
|
dropdownClassName,
|
||||||
transitionName,
|
dropdownAlign,
|
||||||
getPopupContainer,
|
transitionName,
|
||||||
children,
|
getPopupContainer,
|
||||||
range,
|
range,
|
||||||
popupPlacement,
|
popupPlacement,
|
||||||
direction,
|
direction,
|
||||||
}: PickerTriggerProps) {
|
}: PickerTriggerProps,
|
||||||
|
{ slots },
|
||||||
|
) {
|
||||||
const dropdownPrefixCls = `${prefixCls}-dropdown`;
|
const dropdownPrefixCls = `${prefixCls}-dropdown`;
|
||||||
|
|
||||||
const getPopupPlacement = () => {
|
const getPopupPlacement = () => {
|
||||||
|
@ -96,7 +99,7 @@ function PickerTrigger({
|
||||||
popupStyle={popupStyle}
|
popupStyle={popupStyle}
|
||||||
getPopupContainer={getPopupContainer}
|
getPopupContainer={getPopupContainer}
|
||||||
>
|
>
|
||||||
{children}
|
{slots.default?.()}
|
||||||
</Trigger>
|
</Trigger>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -811,7 +811,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
className={classNames({
|
class={classNames({
|
||||||
[`${prefixCls}-panel-focused`]:
|
[`${prefixCls}-panel-focused`]:
|
||||||
mergedActivePickerIndex === 0 ? !startTyping : !endTyping,
|
mergedActivePickerIndex === 0 ? !startTyping : !endTyping,
|
||||||
})}
|
})}
|
||||||
|
@ -938,9 +938,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
|
|
||||||
let mergedNodes: React.ReactNode = (
|
let mergedNodes: React.ReactNode = (
|
||||||
<>
|
<>
|
||||||
<div className={`${prefixCls}-panels`}>{panels}</div>
|
<div class={`${prefixCls}-panels`}>{panels}</div>
|
||||||
{(extraNode || rangesNode) && (
|
{(extraNode || rangesNode) && (
|
||||||
<div className={`${prefixCls}-footer`}>
|
<div class={`${prefixCls}-footer`}>
|
||||||
{extraNode}
|
{extraNode}
|
||||||
{rangesNode}
|
{rangesNode}
|
||||||
</div>
|
</div>
|
||||||
|
@ -954,7 +954,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${prefixCls}-panel-container`}
|
class={`${prefixCls}-panel-container`}
|
||||||
style={{ marginLeft: panelLeft }}
|
style={{ marginLeft: panelLeft }}
|
||||||
ref={panelDivRef}
|
ref={panelDivRef}
|
||||||
onMouseDown={e => {
|
onMouseDown={e => {
|
||||||
|
@ -968,10 +968,10 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
|
|
||||||
const rangePanel = (
|
const rangePanel = (
|
||||||
<div
|
<div
|
||||||
className={classNames(`${prefixCls}-range-wrapper`, `${prefixCls}-${picker}-range-wrapper`)}
|
class={classNames(`${prefixCls}-range-wrapper`, `${prefixCls}-${picker}-range-wrapper`)}
|
||||||
style={{ minWidth: popupMinWidth }}
|
style={{ minWidth: popupMinWidth }}
|
||||||
>
|
>
|
||||||
<div className={`${prefixCls}-range-arrow`} style={arrowPositionStyle} />
|
<div class={`${prefixCls}-range-arrow`} style={arrowPositionStyle} />
|
||||||
|
|
||||||
{renderPanels()}
|
{renderPanels()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -980,7 +980,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
// ============================= Icons =============================
|
// ============================= Icons =============================
|
||||||
let suffixNode: React.ReactNode;
|
let suffixNode: React.ReactNode;
|
||||||
if (suffixIcon) {
|
if (suffixIcon) {
|
||||||
suffixNode = <span className={`${prefixCls}-suffix`}>{suffixIcon}</span>;
|
suffixNode = <span class={`${prefixCls}-suffix`}>{suffixIcon}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clearNode: React.ReactNode;
|
let clearNode: React.ReactNode;
|
||||||
|
@ -1010,9 +1010,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
triggerChange(values, null);
|
triggerChange(values, null);
|
||||||
triggerOpen(false, mergedActivePickerIndex);
|
triggerOpen(false, mergedActivePickerIndex);
|
||||||
}}
|
}}
|
||||||
className={`${prefixCls}-clear`}
|
class={`${prefixCls}-clear`}
|
||||||
>
|
>
|
||||||
{clearIcon || <span className={`${prefixCls}-clear-btn`} />}
|
{clearIcon || <span class={`${prefixCls}-clear-btn`} />}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1077,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={classNames(prefixCls, `${prefixCls}-range`, className, {
|
class={classNames(prefixCls, `${prefixCls}-range`, className, {
|
||||||
[`${prefixCls}-disabled`]: mergedDisabled[0] && mergedDisabled[1],
|
[`${prefixCls}-disabled`]: mergedDisabled[0] && mergedDisabled[1],
|
||||||
[`${prefixCls}-focused`]: mergedActivePickerIndex === 0 ? startFocused : endFocused,
|
[`${prefixCls}-focused`]: mergedActivePickerIndex === 0 ? startFocused : endFocused,
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
|
@ -1090,7 +1090,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
{...getDataOrAriaProps(props)}
|
{...getDataOrAriaProps(props)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(`${prefixCls}-input`, {
|
class={classNames(`${prefixCls}-input`, {
|
||||||
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 0,
|
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 0,
|
||||||
[`${prefixCls}-input-placeholder`]: !!startHoverValue,
|
[`${prefixCls}-input-placeholder`]: !!startHoverValue,
|
||||||
})}
|
})}
|
||||||
|
@ -1112,11 +1112,11 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
autoComplete={autoComplete}
|
autoComplete={autoComplete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${prefixCls}-range-separator`} ref={separatorRef}>
|
<div class={`${prefixCls}-range-separator`} ref={separatorRef}>
|
||||||
{separator}
|
{separator}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={classNames(`${prefixCls}-input`, {
|
class={classNames(`${prefixCls}-input`, {
|
||||||
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 1,
|
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 1,
|
||||||
[`${prefixCls}-input-placeholder`]: !!endHoverValue,
|
[`${prefixCls}-input-placeholder`]: !!endHoverValue,
|
||||||
})}
|
})}
|
||||||
|
@ -1137,7 +1137,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${prefixCls}-active-bar`}
|
class={`${prefixCls}-active-bar`}
|
||||||
style={{
|
style={{
|
||||||
...activeBarPositionStyle,
|
...activeBarPositionStyle,
|
||||||
width: activeBarWidth,
|
width: activeBarWidth,
|
||||||
|
|
|
@ -8,7 +8,8 @@ import type { SharedTimeProps } from '.';
|
||||||
import { setTime as utilSetTime } from '../../utils/timeUtil';
|
import { setTime as utilSetTime } from '../../utils/timeUtil';
|
||||||
import { cloneElement } from '../../../_util/vnode';
|
import { cloneElement } from '../../../_util/vnode';
|
||||||
import { VueNode } from '../../../_util/type';
|
import { VueNode } from '../../../_util/type';
|
||||||
import { Ref } from '@vue/reactivity';
|
import { ref, Ref } from '@vue/reactivity';
|
||||||
|
import { computed, defineComponent, watchEffect } from '@vue/runtime-core';
|
||||||
|
|
||||||
function shouldUnitsUpdate(prevUnits: Unit[], nextUnits: Unit[]) {
|
function shouldUnitsUpdate(prevUnits: Unit[], nextUnits: Unit[]) {
|
||||||
if (prevUnits.length !== nextUnits.length) return true;
|
if (prevUnits.length !== nextUnits.length) return true;
|
||||||
|
@ -50,200 +51,224 @@ export type TimeBodyProps<DateType> = {
|
||||||
operationRef: Ref<BodyOperationRef | undefined>;
|
operationRef: Ref<BodyOperationRef | undefined>;
|
||||||
} & SharedTimeProps<DateType>;
|
} & SharedTimeProps<DateType>;
|
||||||
|
|
||||||
function TimeBody<DateType>(props: TimeBodyProps<DateType>) {
|
|
||||||
const {
|
|
||||||
generateConfig,
|
|
||||||
prefixCls,
|
|
||||||
operationRef,
|
|
||||||
activeColumnIndex,
|
|
||||||
value,
|
|
||||||
showHour,
|
|
||||||
showMinute,
|
|
||||||
showSecond,
|
|
||||||
use12Hours,
|
|
||||||
hourStep = 1,
|
|
||||||
minuteStep = 1,
|
|
||||||
secondStep = 1,
|
|
||||||
disabledHours,
|
|
||||||
disabledMinutes,
|
|
||||||
disabledSeconds,
|
|
||||||
hideDisabledOptions,
|
|
||||||
onSelect,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const columns: {
|
const TimeBody = defineComponent({
|
||||||
node: VueNode;
|
name: 'TimeBody',
|
||||||
value: number;
|
inheritAttrs: false,
|
||||||
units: Unit[];
|
props: [
|
||||||
onSelect: (diff: number) => void;
|
'generateConfig',
|
||||||
}[] = [];
|
'prefixCls',
|
||||||
const contentPrefixCls = `${prefixCls}-content`;
|
'operationRef',
|
||||||
const columnPrefixCls = `${prefixCls}-time-panel`;
|
'activeColumnIndex',
|
||||||
|
'value',
|
||||||
let isPM: boolean | undefined;
|
'showHour',
|
||||||
const originHour = value ? generateConfig.getHour(value) : -1;
|
'showMinute',
|
||||||
let hour = originHour;
|
'showSecond',
|
||||||
const minute = value ? generateConfig.getMinute(value) : -1;
|
'use12Hours',
|
||||||
const second = value ? generateConfig.getSecond(value) : -1;
|
'hourStep',
|
||||||
|
'minuteStep',
|
||||||
const setTime = (
|
'secondStep',
|
||||||
isNewPM: boolean | undefined,
|
'disabledHours',
|
||||||
newHour: number,
|
'disabledMinutes',
|
||||||
newMinute: number,
|
'disabledSeconds',
|
||||||
newSecond: number,
|
'hideDisabledOptions',
|
||||||
) => {
|
'onSelect',
|
||||||
let newDate = value || generateConfig.getNow();
|
],
|
||||||
|
setup(props) {
|
||||||
const mergedHour = Math.max(0, newHour);
|
const originHour = computed(() => props.value ? props.generateConfig.getHour(props.value) : -1);
|
||||||
const mergedMinute = Math.max(0, newMinute);
|
const isPM = computed(()=> {
|
||||||
const mergedSecond = Math.max(0, newSecond);
|
if (props.use12Hours) {
|
||||||
|
return originHour.value >= 12; // -1 means should display AM
|
||||||
newDate = utilSetTime(
|
|
||||||
generateConfig,
|
|
||||||
newDate,
|
|
||||||
!use12Hours || !isNewPM ? mergedHour : mergedHour + 12,
|
|
||||||
mergedMinute,
|
|
||||||
mergedSecond,
|
|
||||||
);
|
|
||||||
|
|
||||||
return newDate;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ========================= Unit =========================
|
|
||||||
const rawHours = generateUnits(0, 23, hourStep, disabledHours && disabledHours());
|
|
||||||
|
|
||||||
const memorizedRawHours = useMemo(() => rawHours, rawHours, shouldUnitsUpdate);
|
|
||||||
|
|
||||||
// Should additional logic to handle 12 hours
|
|
||||||
if (use12Hours) {
|
|
||||||
isPM = hour >= 12; // -1 means should display AM
|
|
||||||
hour %= 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [AMDisabled, PMDisabled] = React.useMemo(() => {
|
|
||||||
if (!use12Hours) {
|
|
||||||
return [false, false];
|
|
||||||
}
|
|
||||||
const AMPMDisabled = [true, true];
|
|
||||||
memorizedRawHours.forEach(({ disabled, value: hourValue }) => {
|
|
||||||
if (disabled) return;
|
|
||||||
if (hourValue >= 12) {
|
|
||||||
AMPMDisabled[1] = false;
|
|
||||||
} else {
|
} else {
|
||||||
AMPMDisabled[0] = false;
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let hour = computed(()=> {
|
||||||
|
// Should additional logic to handle 12 hours
|
||||||
|
if (props.use12Hours) {
|
||||||
|
return originHour.value % 12
|
||||||
|
} else {
|
||||||
|
return originHour.value
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return AMPMDisabled;
|
const minute = computed(()=> props.value ? props.generateConfig.getMinute(props.value) : -1);
|
||||||
}, [use12Hours, memorizedRawHours]);
|
const second = computed(()=> props.value ? props.generateConfig.getSecond(props.value) : -1);
|
||||||
|
|
||||||
const hours = React.useMemo(() => {
|
|
||||||
if (!use12Hours) return memorizedRawHours;
|
|
||||||
return memorizedRawHours
|
const setTime = (
|
||||||
.filter(isPM ? hourMeta => hourMeta.value >= 12 : hourMeta => hourMeta.value < 12)
|
isNewPM: boolean | undefined,
|
||||||
.map(hourMeta => {
|
newHour: number,
|
||||||
const hourValue = hourMeta.value % 12;
|
newMinute: number,
|
||||||
const hourLabel = hourValue === 0 ? '12' : leftPad(hourValue, 2);
|
newSecond: number,
|
||||||
return {
|
) => {
|
||||||
...hourMeta,
|
let newDate = props.value || props.generateConfig.getNow();
|
||||||
label: hourLabel,
|
|
||||||
value: hourValue,
|
const mergedHour = Math.max(0, newHour);
|
||||||
};
|
const mergedMinute = Math.max(0, newMinute);
|
||||||
|
const mergedSecond = Math.max(0, newSecond);
|
||||||
|
|
||||||
|
newDate = utilSetTime(
|
||||||
|
props.generateConfig,
|
||||||
|
newDate,
|
||||||
|
!props.use12Hours || !isNewPM ? mergedHour : mergedHour + 12,
|
||||||
|
mergedMinute,
|
||||||
|
mergedSecond,
|
||||||
|
);
|
||||||
|
|
||||||
|
return newDate;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========================= Unit =========================
|
||||||
|
const rawHours = computed(()=> generateUnits(0, 23, props.hourStep ?? 1, props.disabledHours && props.disabledHours()));
|
||||||
|
|
||||||
|
// const memorizedRawHours = useMemo(() => rawHours, rawHours, shouldUnitsUpdate);
|
||||||
|
|
||||||
|
const AMPMDisabled = computed(() => {
|
||||||
|
if (!props.use12Hours) {
|
||||||
|
return [false, false];
|
||||||
|
}
|
||||||
|
const AMPMDisabled = [true, true];
|
||||||
|
rawHours.value.forEach(({ disabled, value: hourValue }) => {
|
||||||
|
if (disabled) return;
|
||||||
|
if (hourValue >= 12) {
|
||||||
|
AMPMDisabled[1] = false;
|
||||||
|
} else {
|
||||||
|
AMPMDisabled[0] = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, [use12Hours, isPM, memorizedRawHours]);
|
return AMPMDisabled;
|
||||||
|
});
|
||||||
|
|
||||||
const minutes = generateUnits(0, 59, minuteStep, disabledMinutes && disabledMinutes(originHour));
|
const hours = computed(() => {
|
||||||
|
if (!props.use12Hours) return rawHours.value;
|
||||||
|
return rawHours.value
|
||||||
|
.filter(isPM ? hourMeta => hourMeta.value >= 12 : hourMeta => hourMeta.value < 12)
|
||||||
|
.map(hourMeta => {
|
||||||
|
const hourValue = hourMeta.value % 12;
|
||||||
|
const hourLabel = hourValue === 0 ? '12' : leftPad(hourValue, 2);
|
||||||
|
return {
|
||||||
|
...hourMeta,
|
||||||
|
label: hourLabel,
|
||||||
|
value: hourValue,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const seconds = generateUnits(
|
const minutes = computed(()=> generateUnits(0, 59, props.minuteStep ?? 1, props.disabledMinutes && props.disabledMinutes(originHour.value)));
|
||||||
0,
|
|
||||||
59,
|
|
||||||
secondStep,
|
|
||||||
disabledSeconds && disabledSeconds(originHour, minute),
|
|
||||||
);
|
|
||||||
|
|
||||||
// ====================== Operations ======================
|
const seconds = computed(()=> generateUnits(
|
||||||
operationRef.value = {
|
0,
|
||||||
onUpDown: diff => {
|
59,
|
||||||
const column = columns[activeColumnIndex];
|
props.secondStep ?? 1,
|
||||||
if (column) {
|
props.disabledSeconds && props.disabledSeconds(originHour.value, minute),
|
||||||
const valueIndex = column.units.findIndex(unit => unit.value === column.value);
|
));
|
||||||
|
|
||||||
const unitLen = column.units.length;
|
return ()=> {
|
||||||
for (let i = 1; i < unitLen; i += 1) {
|
const {
|
||||||
const nextUnit = column.units[(valueIndex + diff * i + unitLen) % unitLen];
|
prefixCls,
|
||||||
|
operationRef,
|
||||||
|
activeColumnIndex,
|
||||||
|
showHour,
|
||||||
|
showMinute,
|
||||||
|
showSecond,
|
||||||
|
use12Hours,
|
||||||
|
hideDisabledOptions,
|
||||||
|
onSelect,
|
||||||
|
} = props;
|
||||||
|
|
||||||
if (nextUnit.disabled !== true) {
|
const columns: {
|
||||||
column.onSelect(nextUnit.value);
|
node: VueNode;
|
||||||
break;
|
value: number;
|
||||||
|
units: Unit[];
|
||||||
|
onSelect: (diff: number) => void;
|
||||||
|
}[] = [];
|
||||||
|
const contentPrefixCls = `${prefixCls}-content`;
|
||||||
|
const columnPrefixCls = `${prefixCls}-time-panel`;
|
||||||
|
|
||||||
|
// ====================== Operations ======================
|
||||||
|
operationRef.value = {
|
||||||
|
onUpDown: diff => {
|
||||||
|
const column = columns[activeColumnIndex];
|
||||||
|
if (column) {
|
||||||
|
const valueIndex = column.units.findIndex(unit => unit.value === column.value);
|
||||||
|
|
||||||
|
const unitLen = column.units.length;
|
||||||
|
for (let i = 1; i < unitLen; i += 1) {
|
||||||
|
const nextUnit = column.units[(valueIndex + diff * i + unitLen) % unitLen];
|
||||||
|
|
||||||
|
if (nextUnit.disabled !== true) {
|
||||||
|
column.onSelect(nextUnit.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// ======================== Render ========================
|
||||||
|
function addColumnNode(
|
||||||
|
condition: boolean | undefined,
|
||||||
|
node: VueNode,
|
||||||
|
columnValue: number,
|
||||||
|
units: Unit[],
|
||||||
|
onColumnSelect: (diff: number) => void,
|
||||||
|
) {
|
||||||
|
if (condition !== false) {
|
||||||
|
columns.push({
|
||||||
|
node: cloneElement(node, {
|
||||||
|
prefixCls: columnPrefixCls,
|
||||||
|
value: columnValue,
|
||||||
|
active: activeColumnIndex === columns.length,
|
||||||
|
onSelect: onColumnSelect,
|
||||||
|
units,
|
||||||
|
hideDisabledOptions,
|
||||||
|
}),
|
||||||
|
onSelect: onColumnSelect,
|
||||||
|
value: columnValue,
|
||||||
|
units,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// ======================== Render ========================
|
// Hour
|
||||||
function addColumnNode(
|
addColumnNode(showHour, <TimeUnitColumn key="hour" />, hour.value, hours.value, num => {
|
||||||
condition: boolean | undefined,
|
onSelect(setTime(isPM.value, num, minute.value, second.value), 'mouse');
|
||||||
node: VueNode,
|
|
||||||
columnValue: number,
|
|
||||||
units: Unit[],
|
|
||||||
onColumnSelect: (diff: number) => void,
|
|
||||||
) {
|
|
||||||
if (condition !== false) {
|
|
||||||
columns.push({
|
|
||||||
node: cloneElement(node, {
|
|
||||||
prefixCls: columnPrefixCls,
|
|
||||||
value: columnValue,
|
|
||||||
active: activeColumnIndex === columns.length,
|
|
||||||
onSelect: onColumnSelect,
|
|
||||||
units,
|
|
||||||
hideDisabledOptions,
|
|
||||||
}),
|
|
||||||
onSelect: onColumnSelect,
|
|
||||||
value: columnValue,
|
|
||||||
units,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Minute
|
||||||
|
addColumnNode(showMinute, <TimeUnitColumn key="minute" />, minute.value, minutes.value, num => {
|
||||||
|
onSelect(setTime(isPM.value, hour.value, num, second.value), 'mouse');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Second
|
||||||
|
addColumnNode(showSecond, <TimeUnitColumn key="second" />, second.value, seconds.value, num => {
|
||||||
|
onSelect(setTime(isPM.value, hour.value, minute.value, num), 'mouse');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 12 Hours
|
||||||
|
let PMIndex = -1;
|
||||||
|
if (typeof isPM === 'boolean') {
|
||||||
|
PMIndex = isPM ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
addColumnNode(
|
||||||
|
use12Hours === true,
|
||||||
|
<TimeUnitColumn key="12hours" />,
|
||||||
|
PMIndex,
|
||||||
|
[
|
||||||
|
{ label: 'AM', value: 0, disabled: AMPMDisabled.value[0] },
|
||||||
|
{ label: 'PM', value: 1, disabled: AMPMDisabled.value[1] },
|
||||||
|
],
|
||||||
|
num => {
|
||||||
|
onSelect(setTime(!!num, hour.value, minute.value, second.value), 'mouse');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return <div class={contentPrefixCls}>{columns.map(({ node }) => node)}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Hour
|
|
||||||
addColumnNode(showHour, <TimeUnitColumn key="hour" />, hour, hours, num => {
|
|
||||||
onSelect(setTime(isPM, num, minute, second), 'mouse');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Minute
|
|
||||||
addColumnNode(showMinute, <TimeUnitColumn key="minute" />, minute, minutes, num => {
|
|
||||||
onSelect(setTime(isPM, hour, num, second), 'mouse');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Second
|
|
||||||
addColumnNode(showSecond, <TimeUnitColumn key="second" />, second, seconds, num => {
|
|
||||||
onSelect(setTime(isPM, hour, minute, num), 'mouse');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 12 Hours
|
|
||||||
let PMIndex = -1;
|
|
||||||
if (typeof isPM === 'boolean') {
|
|
||||||
PMIndex = isPM ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
addColumnNode(
|
|
||||||
use12Hours === true,
|
|
||||||
<TimeUnitColumn key="12hours" />,
|
|
||||||
PMIndex,
|
|
||||||
[
|
|
||||||
{ label: 'AM', value: 0, disabled: AMDisabled },
|
|
||||||
{ label: 'PM', value: 1, disabled: PMDisabled },
|
|
||||||
],
|
|
||||||
num => {
|
|
||||||
onSelect(setTime(!!num, hour, minute, second), 'mouse');
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return <div class={contentPrefixCls}>{columns.map(({ node }) => node)}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TimeBody.displayName ='TimeBody'
|
|
||||||
TimeBody.inheritAttrs = false;
|
|
||||||
|
|
||||||
export default TimeBody;
|
export default TimeBody;
|
||||||
|
|
Loading…
Reference in New Issue