Skip to content

Commit 83a33a7

Browse files
committed
feat(ui): add date-picker component
1 parent d70e541 commit 83a33a7

53 files changed

Lines changed: 1760 additions & 515 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/site/src/app/styles/_app.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ h3 {
225225
'Radio': 'radio',
226226
'Input': 'input',
227227
'Switch': 'switch',
228-
'Time-picker': 'time-picker'
228+
'Time-picker': 'time-picker',
229+
'Date-picker': 'date-picker'
229230
)
230231
{
231232
section[id^='#{$id}'] {

packages/ui/src/components/_time-input/TimeInput.tsx renamed to packages/ui/src/components/_date-input/DateInput.tsx

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,30 @@ import {
1515
useElement,
1616
useUpdatePosition,
1717
} from '../../hooks';
18-
import { ClockCircleOutlined, CloseCircleFilled, SwapRightOutlined } from '../../icons';
18+
import { CloseCircleFilled, SwapRightOutlined } from '../../icons';
1919
import { getClassName, getNoTransformSize, getVerticalSidePosition } from '../../utils';
2020
import { ICON_SIZE } from '../../utils/global';
2121
import { DBaseDesign } from '../_base-design';
2222
import { DBaseInput } from '../_base-input';
2323
import { DTransition } from '../_transition';
2424

25-
export type DExtendsTimeInputProps = Pick<
26-
DTimeInputProps,
27-
'dFormControl' | 'dPlacement' | 'dSize' | 'dRange' | 'dClearable' | 'dDisabled' | 'onClear' | 'onVisibleChange'
28-
>;
29-
30-
export interface DTimeInputRef {
25+
export interface DDateInputRef {
3126
updatePosition: () => void;
3227
}
3328

34-
export interface DTimeInputRenderProps {
35-
tiStyle: React.CSSProperties;
36-
'data-time-input-popupid': string;
37-
tiOnMouseDown: React.MouseEventHandler;
38-
tiOnMouseUp: React.MouseEventHandler;
29+
export interface DDateInputRenderProps {
30+
diStyle: React.CSSProperties;
31+
'data-date-input-popupid': string;
32+
diOnMouseDown: React.MouseEventHandler;
33+
diOnMouseUp: React.MouseEventHandler;
3934
}
4035

41-
export interface DTimeInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
42-
children: (props: DTimeInputRenderProps) => JSX.Element | null;
36+
export interface DDateInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
37+
children: (props: DDateInputRenderProps) => JSX.Element | null;
4338
dFormControl?: DFormControl;
4439
dVisible?: boolean;
4540
dPlacement?: 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right';
41+
dSuffix?: React.ReactNode;
4642
dSize?: DSize;
4743
dRange?: boolean;
4844
dClearable?: boolean;
@@ -54,16 +50,17 @@ export interface DTimeInputProps extends Omit<React.HTMLAttributes<HTMLDivElemen
5450
}
5551

5652
const TTANSITION_DURING = 116;
57-
function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef>) {
53+
function DateInput(props: DDateInputProps, ref: React.ForwardedRef<DDateInputRef>) {
5854
const {
5955
children,
6056
dFormControl,
61-
dVisible = false,
57+
dVisible,
58+
dSuffix,
6259
dPlacement = 'bottom-left',
6360
dSize,
64-
dRange = false,
65-
dClearable = false,
66-
dDisabled = false,
61+
dRange,
62+
dClearable,
63+
dDisabled,
6764
dInputProps,
6865
dInputRef,
6966
onVisibleChange,
@@ -117,10 +114,10 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
117114
const clearable = dClearable && !dVisible && !dDisabled;
118115

119116
const containerEl = useElement(() => {
120-
let el = document.getElementById(`${dPrefix}time-input-root`);
117+
let el = document.getElementById(`${dPrefix}date-input-root`);
121118
if (!el) {
122119
el = document.createElement('div');
123-
el.id = `${dPrefix}time-input-root`;
120+
el.id = `${dPrefix}date-input-root`;
124121
document.body.appendChild(el);
125122
}
126123
return el;
@@ -134,7 +131,7 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
134131
});
135132
const [transformOrigin, setTransformOrigin] = useState<string>();
136133
const updatePosition = useEventCallback(() => {
137-
const popupEl = document.querySelector(`[data-time-input-popupid="${uniqueId}"]`) as HTMLElement | null;
134+
const popupEl = document.querySelector(`[data-date-input-popupid="${uniqueId}"]`) as HTMLElement | null;
138135
if (boxRef.current && popupEl) {
139136
const { width, height } = getNoTransformSize(popupEl);
140137
const { top, left, transformOrigin } = getVerticalSidePosition(boxRef.current, { width, height }, dPlacement, 8);
@@ -155,7 +152,7 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
155152
});
156153
}
157154

158-
const popupEl = document.querySelector(`[data-time-input-popupid="${uniqueId}"]`) as HTMLElement | null;
155+
const popupEl = document.querySelector(`[data-date-input-popupid="${uniqueId}"]`) as HTMLElement | null;
159156
if (popupEl) {
160157
asyncGroup.onResize(popupEl, () => {
161158
updatePosition();
@@ -221,7 +218,7 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
221218
<DBaseInput
222219
{...inputProps}
223220
ref={isLeft ? combineInputRefLeft : combineInputRefRight}
224-
className={getClassName(inputProps?.className, `${dPrefix}time-input__input`)}
221+
className={getClassName(inputProps?.className, `${dPrefix}date-input__input`)}
225222
type="text"
226223
autoComplete="off"
227224
disabled={dDisabled}
@@ -271,8 +268,8 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
271268
<div
272269
{...restProps}
273270
ref={boxRef}
274-
className={getClassName(className, `${dPrefix}time-input`, {
275-
[`${dPrefix}time-input--${dSize}`]: dSize,
271+
className={getClassName(className, `${dPrefix}date-input`, {
272+
[`${dPrefix}date-input--${dSize}`]: dSize,
276273
'is-disabled': dDisabled,
277274
'is-focus': isFocus,
278275
})}
@@ -298,14 +295,14 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
298295
{getInputNode(true)}
299296
{dRange && (
300297
<>
301-
<div ref={indicatorRef} className={`${dPrefix}time-input__indicator`}></div>
302-
<SwapRightOutlined className={`${dPrefix}time-input__separator`} />
298+
<div ref={indicatorRef} className={`${dPrefix}date-input__indicator`}></div>
299+
<SwapRightOutlined className={`${dPrefix}date-input__separator`} />
303300
{getInputNode(false)}
304301
</>
305302
)}
306303
{clearable && (
307304
<button
308-
className={getClassName(`${dPrefix}icon-button`, `${dPrefix}time-input__clear`)}
305+
className={getClassName(`${dPrefix}icon-button`, `${dPrefix}date-input__clear`)}
309306
style={{ width: iconSize, height: iconSize }}
310307
aria-label={t('Common', 'Clear')}
311308
onClick={(e) => {
@@ -317,7 +314,11 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
317314
<CloseCircleFilled dSize={iconSize} />
318315
</button>
319316
)}
320-
<ClockCircleOutlined className={`${dPrefix}time-input__icon`} style={{ opacity: clearable ? 0 : 1 }} dSize={iconSize} />
317+
{dSuffix && (
318+
<div className={`${dPrefix}date-input__icon`} style={{ opacity: clearable ? 0 : 1, fontSize: iconSize }}>
319+
{dSuffix}
320+
</div>
321+
)}
321322
</div>
322323
</DBaseDesign>
323324
{containerEl &&
@@ -355,14 +356,14 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
355356
}
356357

357358
return children({
358-
tiStyle: {
359+
diStyle: {
359360
...popupPositionStyle,
360361
...transitionStyle,
361362
zIndex: maxZIndex,
362363
},
363-
'data-time-input-popupid': uniqueId,
364-
tiOnMouseDown: preventBlur,
365-
tiOnMouseUp: preventBlur,
364+
'data-date-input-popupid': uniqueId,
365+
diOnMouseDown: preventBlur,
366+
diOnMouseUp: preventBlur,
366367
});
367368
}}
368369
</DTransition>,
@@ -372,4 +373,4 @@ function TimeInput(props: DTimeInputProps, ref: React.ForwardedRef<DTimeInputRef
372373
);
373374
}
374375

375-
export const DTimeInput = React.forwardRef(TimeInput);
376+
export const DDateInput = React.forwardRef(DateInput);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './DateInput';

packages/ui/src/components/_popup/Popup.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ import { filter } from 'rxjs';
55

66
import { useAsync, useElement, useEventCallback, usePrefixConfig, useUpdatePosition } from '../../hooks';
77

8-
export type DExtendsPopupProps = Pick<
9-
DPopupProps,
10-
'dDisabled' | 'dTrigger' | 'dMouseEnterDelay' | 'dMouseLeaveDelay' | 'dEscClosable' | 'onVisibleChange'
11-
>;
12-
138
export interface DPopupPopupRenderProps {
149
'data-popup-popupid': string;
1510
pOnMouseEnter?: React.MouseEventHandler;
@@ -31,7 +26,7 @@ export interface DPopupProps {
3126
dVisible: boolean;
3227
dPopup: (props: DPopupPopupRenderProps) => JSX.Element | null;
3328
dContainer?: HTMLElement | null;
34-
dTrigger?: 'hover' | 'focus' | 'click';
29+
dTrigger: 'hover' | 'focus' | 'click';
3530
dDisabled?: boolean;
3631
dEscClosable?: boolean;
3732
dMouseEnterDelay?: number;
@@ -46,9 +41,9 @@ export function DPopup(props: DPopupProps) {
4641
dVisible,
4742
dPopup,
4843
dContainer,
49-
dTrigger = 'hover',
50-
dDisabled = false,
51-
dEscClosable = true,
44+
dTrigger,
45+
dDisabled,
46+
dEscClosable,
5247
dMouseEnterDelay = 150,
5348
dMouseLeaveDelay = 200,
5449
onVisibleChange,

packages/ui/src/components/_selectbox/Selectbox.tsx

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,6 @@ import { DBaseInput } from '../_base-input';
2424
import { DFocusVisible } from '../_focus-visible';
2525
import { DTransition } from '../_transition';
2626

27-
export type DExtendsSelectboxProps = Pick<
28-
DSelectboxProps,
29-
| 'dFormControl'
30-
| 'dPlaceholder'
31-
| 'dSize'
32-
| 'dLoading'
33-
| 'dSearchable'
34-
| 'dClearable'
35-
| 'dDisabled'
36-
| 'dInputProps'
37-
| 'dInputRef'
38-
| 'onClear'
39-
| 'onVisibleChange'
40-
>;
41-
4227
export interface DSelectboxRef {
4328
updatePosition: () => void;
4429
}
@@ -76,16 +61,16 @@ function Selectbox(props: DSelectboxProps, ref: React.ForwardedRef<DSelectboxRef
7661
const {
7762
children,
7863
dFormControl,
79-
dVisible = false,
64+
dVisible,
8065
dContent,
8166
dContentTitle,
8267
dPlaceholder,
8368
dSuffix,
8469
dSize,
85-
dLoading = false,
86-
dSearchable = false,
87-
dClearable = false,
88-
dDisabled = false,
70+
dLoading,
71+
dSearchable,
72+
dClearable,
73+
dDisabled,
8974
dInputProps,
9075
dInputRef,
9176
onUpdatePosition,

packages/ui/src/components/_time-input/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/ui/src/components/_transition/Transition.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const [T_ENTER, T_ENTERING, T_ENTERED, T_LEAVE, T_LEAVING, T_LEAVED] = [
1515

1616
export interface DTransitionProps {
1717
children: (state: DTransitionState) => JSX.Element | null;
18-
dIn: boolean;
18+
dIn?: boolean;
1919
dDuring: number | { enter: number; leave: number };
2020
dMountBeforeFirstEnter?: boolean;
2121
dSkipFirstTransition?: boolean | [boolean, boolean];
@@ -27,7 +27,7 @@ export interface DTransitionProps {
2727
export function DTransition(props: DTransitionProps) {
2828
const {
2929
children,
30-
dIn,
30+
dIn = false,
3131
dDuring,
3232
dMountBeforeFirstEnter = true,
3333
dSkipFirstTransition = true,

packages/ui/src/components/cascader/Cascader.tsx

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { DId, DNestedChildren } from '../../utils/global';
2-
import type { DExtendsSelectboxProps } from '../_selectbox';
1+
import type { DId, DNestedChildren, DSize } from '../../utils/global';
32
import type { DDropdownOption } from '../dropdown';
3+
import type { DFormControl } from '../form';
44
import type { DSelectOption } from '../select';
55
import type { AbstractTreeNode } from '../tree';
66

@@ -34,12 +34,17 @@ export interface DCascaderOption<V extends DId> {
3434
disabled?: boolean;
3535
}
3636

37-
export interface DCascaderProps<V extends DId, T extends DCascaderOption<V>>
38-
extends React.HTMLAttributes<HTMLDivElement>,
39-
DExtendsSelectboxProps {
37+
export interface DCascaderProps<V extends DId, T extends DCascaderOption<V>> extends React.HTMLAttributes<HTMLDivElement> {
38+
dFormControl?: DFormControl;
4039
dModel?: V | null | V[];
4140
dOptions: DNestedChildren<T>[];
4241
dVisible?: boolean;
42+
dPlaceholder?: string;
43+
dSize?: DSize;
44+
dLoading?: boolean;
45+
dSearchable?: boolean;
46+
dClearable?: boolean;
47+
dDisabled?: boolean;
4348
dMultiple?: boolean;
4449
dOnlyLeafSelectable?: boolean;
4550
dCustomOption?: (option: DNestedChildren<T>) => React.ReactNode;
@@ -49,35 +54,41 @@ export interface DCascaderProps<V extends DId, T extends DCascaderOption<V>>
4954
sort?: (a: DNestedChildren<T>, b: DNestedChildren<T>) => number;
5055
};
5156
dPopupClassName?: string;
57+
dInputProps?: React.InputHTMLAttributes<HTMLInputElement>;
58+
dInputRef?: React.Ref<HTMLInputElement>;
5259
onModelChange?: (value: any, option: any) => void;
60+
onVisibleChange?: (visible: boolean) => void;
5361
onSearch?: (value: string) => void;
62+
onClear?: () => void;
5463
onFocusChange?: (value: V, option: DNestedChildren<T>) => void;
5564
}
5665

5766
const { COMPONENT_NAME } = registerComponentMate({ COMPONENT_NAME: 'DCascader' });
5867
function Cascader<V extends DId, T extends DCascaderOption<V>>(props: DCascaderProps<V, T>, ref: React.ForwardedRef<DCascaderRef>) {
5968
const {
69+
dFormControl,
6070
dModel,
6171
dOptions,
6272
dVisible,
73+
dPlaceholder,
74+
dSize,
75+
dLoading = false,
76+
dSearchable = false,
77+
dClearable = false,
78+
dDisabled = false,
6379
dMultiple = false,
6480
dOnlyLeafSelectable = true,
6581
dCustomOption,
6682
dCustomSelected,
6783
dCustomSearch,
6884
dPopupClassName,
69-
onModelChange,
70-
onSearch,
71-
onFocusChange,
72-
73-
dFormControl,
74-
dLoading,
75-
dSearchable,
76-
dDisabled,
77-
dSize,
7885
dInputProps,
86+
dInputRef,
87+
onModelChange,
7988
onVisibleChange,
89+
onSearch,
8090
onClear,
91+
onFocusChange,
8192

8293
className,
8394
...restProps
@@ -348,10 +359,12 @@ function Cascader<V extends DId, T extends DCascaderOption<V>>(props: DCascaderP
348359
dVisible={visible}
349360
dContent={hasSelected && selectedNode}
350361
dContentTitle={selectedLabel}
362+
dPlaceholder={dPlaceholder}
351363
dSuffix={suffixNode}
352364
dSize={size}
353365
dLoading={dLoading}
354366
dSearchable={dSearchable}
367+
dClearable={dClearable}
355368
dDisabled={disabled}
356369
dInputProps={{
357370
...dInputProps,
@@ -374,6 +387,7 @@ function Cascader<V extends DId, T extends DCascaderOption<V>>(props: DCascaderP
374387
}
375388
},
376389
}}
390+
dInputRef={dInputRef}
377391
onUpdatePosition={(boxEl) => {
378392
const popupEl = popupRef.current;
379393
if (popupEl) {

0 commit comments

Comments
 (0)