Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/ui/src/DateRanger/EditableDateTimeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Moment } from 'moment';
import classNames from 'classnames';
import { Input } from '@oceanbase/design';
import { useSegmentedInput } from './hooks/useSegmentedInput';
import { useAutoWidthInput } from './hooks/useAutoWidthInput';

export interface EditableDateTimeInputProps {
value?: [Dayjs | Moment | null, Dayjs | Moment | null];
Expand Down Expand Up @@ -95,6 +96,12 @@ const EditableDateTimeInput = forwardRef<EditableDateTimeInputRef, EditableDateT
open,
});

const { sizerRef, inputWidth } = useAutoWidthInput({
inputRef,
value: displayValue,
minWidth: 80,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果支持宽度自适应,当手动修改日期时间,宽度不断变化、导致抖动吧

});

// 暴露方法给父组件
useImperativeHandle(ref, () => ({
hasPastedValue,
Expand All @@ -108,9 +115,11 @@ const EditableDateTimeInput = forwardRef<EditableDateTimeInputRef, EditableDateT
[`${prefixCls}-range-editable-disabled`]: disabled,
})}
>
<span ref={sizerRef} className={`${prefixCls}-range-editable-sizer`} aria-hidden />
<Input
ref={inputRef}
className={`${prefixCls}-range-editable-input`}
style={{ width: inputWidth }}
value={displayValue}
readOnly
disabled={disabled}
Expand Down
6 changes: 5 additions & 1 deletion packages/ui/src/DateRanger/Ranger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export type RangeDateValue = {

export interface DateRangerProps extends Omit<
RangePickerProps,
'mode' | 'picker' | 'value' | 'defaultValue'
'mode' | 'picker' | 'value' | 'defaultValue' | 'variant'
> {
// 数据相关
selects?: RangeOption[];
Expand Down Expand Up @@ -118,6 +118,8 @@ export interface DateRangerProps extends Omit<
value?: RangeValue;
defaultValue?: RangeValue;
size?: 'small' | 'large' | 'middle';
/** 边框变体,默认实线,可配置为 dashed 虚线 */
variant?: 'dashed';
tooltipProps?: TooltipProps;
autoAdjustOverflow?: boolean;
overlayClassName?: string;
Expand Down Expand Up @@ -163,6 +165,7 @@ const Ranger = React.forwardRef((props: DateRangerProps, ref) => {
size,
//固定 rangeName
stickRangeName = false,
variant,
tooltipProps,
isMoment: isMomentProps,
rules,
Expand Down Expand Up @@ -437,6 +440,7 @@ const Ranger = React.forwardRef((props: DateRangerProps, ref) => {
className={classNames(rest.className, {
[prefix]: true,
[`${prefix}-show-range`]: true,
[`${prefix}-dashed`]: variant === 'dashed',
[`${prefix}-back-radio-focused`]: backRadioFocused,
})}
style={rest.style}
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/DateRanger/demo/copy-paste.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import zhCN from '@oceanbase/ui/locale/zh-CN';

export default () => {
const [locale, setLocal] = useState(enUS);
const [format, setFormat] = useState('MMM DD, YYYY HH:mm:ss');
const [format, setFormat] = useState('MMM DD, YYYY HH:mm:ss(UTC+8)');
// 初始化时设置 dayjs locale
React.useEffect(() => {
dayjs.locale('en');
Expand All @@ -18,10 +18,10 @@ export default () => {
setLocal(localeValue);
if (localeValue === enUS || (localeValue as any)?.locale === 'en') {
dayjs.locale('en');
setFormat('MMM DD, YYYY HH:mm:ss');
setFormat('MMM DD, YYYY HH:mm:ss(UTC+8)');
} else {
dayjs.locale('zh-cn');
setFormat('YYYY-MM-DD HH:mm:ss');
setFormat('YYYY-MM-DD HH:mm:ss(UTC+8)');
}
};

Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/DateRanger/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { useSegmentedInput } from './useSegmentedInput';
export { useAutoWidthInput } from './useAutoWidthInput';

export type { UseSegmentedInputOptions, UseSegmentedInputReturn } from './useSegmentedInput';
export type { UseAutoWidthInputOptions, UseAutoWidthInputReturn } from './useAutoWidthInput';
50 changes: 50 additions & 0 deletions packages/ui/src/DateRanger/hooks/useAutoWidthInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useLayoutEffect, useRef, useState } from 'react';
import type { InputRef } from '@oceanbase/design';

const getHorizontalSpacing = (computedStyle: CSSStyleDeclaration) =>
(parseFloat(computedStyle.paddingLeft) || 0) +
(parseFloat(computedStyle.paddingRight) || 0) +
(parseFloat(computedStyle.borderLeftWidth) || 0) +
(parseFloat(computedStyle.borderRightWidth) || 0);

const getSizingValue = (value: string) => (value ? value.replace(/\d/g, '0') : '\u00a0');

export interface UseAutoWidthInputOptions {
inputRef: React.RefObject<InputRef>;
value: string;
minWidth?: number;
}

export interface UseAutoWidthInputReturn {
inputWidth: number;
sizerRef: React.RefObject<HTMLSpanElement>;
}

export const useAutoWidthInput = (options: UseAutoWidthInputOptions): UseAutoWidthInputReturn => {
const { inputRef, value, minWidth = 80 } = options;
const sizerRef = useRef<HTMLSpanElement>(null);
const [inputWidth, setInputWidth] = useState<number>(minWidth);

useLayoutEffect(() => {
const nativeInput = inputRef.current?.input;
const sizer = sizerRef.current;
if (!nativeInput || !sizer) {
return;
}

const computedStyle = window.getComputedStyle(nativeInput);
sizer.style.font = computedStyle.font;
sizer.style.letterSpacing = computedStyle.letterSpacing;
sizer.style.fontVariantNumeric = computedStyle.fontVariantNumeric;
sizer.textContent = getSizingValue(value);

setInputWidth(
Math.max(minWidth, Math.ceil(sizer.offsetWidth + getHorizontalSpacing(computedStyle)))
);
}, [inputRef, minWidth, value]);

return {
inputWidth,
sizerRef,
};
};
1 change: 1 addition & 0 deletions packages/ui/src/DateRanger/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ markdown: |
| overlayClassName | 选择面板根元素的类名称 | string | - | - |
| overlayStyle | 选择面板根元素的样式 | CSSProperties | - | - |
| ref | updateCurrentTime 手动更新当前时间 | function | - | - |
| variant | 边框变体 | 'dashed' | - | - |
| history | 开启历史记录, 可以配置最大保留的记录条数,默认20条 | boolean \| { capacity: number } | false | - |
| 其他 antd/RangePicker 的 `props` | [antd-RangePicker](https://ant.design/components/date-picker-cn/#RangePicker) | - | - | - |

Expand Down
28 changes: 27 additions & 1 deletion packages/ui/src/DateRanger/style/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ export const genDateRangerStyle: GenerateStyle<DateRangerToken> = (
borderRadius: token.borderRadiusSM,
textAlign: 'center',
},
[`${componentCls}-dashed`]: {
[`${componentCls}-wrapper`]: {
borderStyle: 'dashed',
},
[`${componentCls}-playback-control`]: {
[`${antCls}-radio-button-wrapper`]: {
borderStyle: 'dashed',
'&::before': {
borderStyle: 'dashed',
},
},
},
},
[`${componentCls}-back-radio-focused`]: {
[`${componentCls}-wrapper`]: {
borderRightColor: token.gray7,
Expand Down Expand Up @@ -172,6 +185,7 @@ export const genDateRangerStyle: GenerateStyle<DateRangerToken> = (
alignItems: 'center',
},
[`${componentCls}-range-editable`]: {
position: 'relative',
display: 'inline-flex',
alignItems: 'center',
cursor: 'text',
Expand All @@ -180,10 +194,22 @@ export const genDateRangerStyle: GenerateStyle<DateRangerToken> = (
opacity: 0.6,
},
},
[`${componentCls}-range-editable-sizer`]: {
position: 'absolute',
top: 0,
left: 0,
height: 0,
overflow: 'hidden',
whiteSpace: 'pre',
visibility: 'hidden',
pointerEvents: 'none',
},
[`${componentCls}-range-editable-input`]: {
width: 310,
minWidth: 80,
maxWidth: '100%',
cursor: 'text',
caretColor: 'transparent',
fontVariantNumeric: 'tabular-nums',
'&:focus, &:focus-within': {
[`${antCls}-input`]: {
caretColor: token.colorPrimary,
Expand Down
Loading