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