Skip to content

Commit

Permalink
feat(select-input): 完成select-input&优化popup
Browse files Browse the repository at this point in the history
  • Loading branch information
duenyang committed Sep 24, 2024
2 parents ddd0f34 + 3c09c5c commit 8f03ef0
Show file tree
Hide file tree
Showing 21 changed files with 1,480 additions and 87 deletions.
1 change: 1 addition & 0 deletions src/input/_example/base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default class InputBase extends Component {
return (
<t-space direction="vertical" style={{ width: 500 }}>
<t-input
value={this.value1}
placeholder="请输入内容(无默认值)"
onChange={(value) => {
this.value1 = value;
Expand Down
60 changes: 42 additions & 18 deletions src/input/input.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'tdesign-icons-web-components/esm/components/close-circle-filled';
import 'tdesign-icons-web-components/esm/components/browse';
import 'tdesign-icons-web-components/esm/components/browse-off';
import 'tdesign-icons-web-components/esm/components/close-circle-filled';

import { cloneElement, Component, createRef, OmiProps, tag, VNode } from 'omi';

Expand Down Expand Up @@ -152,6 +152,8 @@ export default class Input extends Component<InputProps> {
onValidateChange();
onChange?.(newStr);
}

this.update();
};

private handleFocus = (e: FocusEvent) => {
Expand Down Expand Up @@ -235,31 +237,44 @@ export default class Input extends Component<InputProps> {
onCompositionend?.(currentTarget.value, { e });
};

private updateInputWidth() {
if (!this.props.autoWidth || !this.inputRef.current) {
return;
}
const { offsetWidth } = this.inputPreRef.current;
const { width } = this.inputPreRef.current.getBoundingClientRect();
// 异步渲染场景下 getBoundingClientRect 宽度为 0,需要使用 offsetWidth
const calcWidth = width < offsetWidth ? offsetWidth + 1 : width;
this.inputRef.current.style.width = `${calcWidth}px`;
}

private resizeObserver: ResizeObserver | null = null;

install() {
this.value = this.props.defaultValue || this.props.value;
this.status = this.props.status;
}

installed() {
ready() {
this.renderType = this.props.type;
const inputNode = this.inputRef.current;
const updateInputWidth = () => {
if (!this.props.autoWidth || !this.inputRef.current) return;
const { offsetWidth } = this.inputPreRef.current;
const { width } = this.inputPreRef.current.getBoundingClientRect();
// 异步渲染场景下 getBoundingClientRect 宽度为 0,需要使用 offsetWidth
const calcWidth = width < offsetWidth ? offsetWidth + 1 : width;
this.inputRef.current.style.width = `${calcWidth}px`;
};

if (this.props.autoWidth) {
requestAnimationFrame(() => {
updateInputWidth();
this.updateInputWidth();
});
}

this.resizeObserver = new ResizeObserver(() => {
this.updateInputWidth();
});

if (!inputNode) return;

inputNode.addEventListener('input', (e) => {
if (this.composingRef.current) {
this.composingValue = (e.currentTarget as HTMLInputElement)?.value || '';
this.update();
return;
}
const target = e.currentTarget as any;
Expand All @@ -279,11 +294,6 @@ export default class Input extends Component<InputProps> {
if (!this.props.allowInputOverMax) {
this.update();
}
if (this.props.autoWidth) {
requestAnimationFrame(() => {
updateInputWidth();
});
}
onValidateChange();
});
}
Expand Down Expand Up @@ -350,6 +360,7 @@ export default class Input extends Component<InputProps> {
if (isShowClearIcon) {
suffixIconNew = (
<t-icon-close-circle-filled
onMouseDown={(e) => e.preventDefault()}
name={'close-circle-filled'}
cls={classname(
`${classPrefix}-input__suffix-clear`,
Expand All @@ -365,6 +376,7 @@ export default class Input extends Component<InputProps> {
if (this.renderType === 'password') {
suffixIconNew = (
<t-icon-browse-off
onMouseDown={(e) => e.preventDefault()}
onClick={this.handlePasswordVisible}
cls={classname(
`${classPrefix}-input__suffix-clear`,
Expand All @@ -377,6 +389,7 @@ export default class Input extends Component<InputProps> {
} else if (this.renderType === 'text') {
suffixIconNew = (
<t-icon-browse
onMouseDown={(e) => e.preventDefault()}
onClick={this.handlePasswordVisible}
cls={classname(
`${classPrefix}-input__suffix-clear`,
Expand All @@ -390,8 +403,8 @@ export default class Input extends Component<InputProps> {
}

const suffixIconContent = renderIcon('t', 'suffix', parseTNode(convertToLightDomNode(suffixIconNew)));
const labelContent = isFunction(label) ? label() : label;
const suffixContent = isFunction(suffix) ? suffix() : suffix;
const labelContent = isFunction(label) ? (label as any)() : label;
const suffixContent = isFunction(suffix) ? (suffix as any)() : suffix;

const limitNumberNode =
limitNumber() && showLimitNumber ? (
Expand Down Expand Up @@ -477,6 +490,10 @@ export default class Input extends Component<InputProps> {
)}
ref={this.wrapperRef}
part="wrap"
onClick={(e) => {
this.inputRef.current?.focus();
restProps.onClick?.(e);
}}
{...restProps}
style={innerStyle}
>
Expand All @@ -487,4 +504,11 @@ export default class Input extends Component<InputProps> {
</div>
);
}

rendered() {
this.resizeObserver?.disconnect();
if (this.inputPreRef.current) {
this.resizeObserver?.observe(this.inputPreRef.current);
}
}
}
1 change: 0 additions & 1 deletion src/popup/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ export default class Popup extends Component<PopupProps> {
return child;
});

console.log('===this.getVisible()', this.getVisible());
return (
<>
{children.length > 1 ? (
Expand Down
87 changes: 77 additions & 10 deletions src/select-input/SelectInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Component, createRef, OmiProps, tag } from 'omi';

import { getClassPrefix } from '../_util/classname';
import { StyledProps } from '../common';
import { PopupVisibleChangeContext } from '../popup';
import { selectInputDefaultProps } from './defaultProps';
import { SelectInputCommonProperties } from './interface';
import { TdSelectInputProps } from './type';
Expand Down Expand Up @@ -49,6 +50,52 @@ class SelectInput extends Component<SelectInputProps> {

static defaultProps = selectInputDefaultProps;

static propTypes = {
allowInput: Boolean,
autoWidth: Boolean,
autofocus: Boolean,
borderless: Boolean,
clearable: Boolean,
collapsedItems: [Function, Object, String, Number],
disabled: Boolean,
inputProps: Object,
inputValue: String,
defaultInputValue: String,
keys: Object,
label: [Function, Object, String, Number],
loading: Boolean,
minCollapsedNum: Number,
multiple: Boolean,
panel: [Function, Object, String, Number],
placeholder: String,
popupProps: Object,
popupVisible: Boolean,
defaultPopupVisible: Boolean,
prefixIcon: [Function, Object, String, Number],
readonly: Boolean,
reserveKeyword: Boolean,
size: String,
status: String,
suffix: [Function, Object, String, Number],
suffixIcon: [Function, Object, String, Number],
tag: [String, Function, Object, Number],
tagInputProps: Object,
tagProps: Object,
tips: [Function, Object, String, Number],
value: [String, Number, Boolean, Object, Array],
valueDisplay: [String, Function, Object, Number],
onBlur: Function,
onClear: Function,
onEnter: Function,
onFocus: Function,
onInputChange: Function,
onMouseenter: Function,
onMouseleave: Function,
onPaste: Function,
onPopupVisibleChange: Function,
onTagChange: Function,
};

selectInputRef = createRef();

selectInputWrapRef = createRef();
Expand All @@ -63,8 +110,12 @@ class SelectInput extends Component<SelectInputProps> {

onInnerPopupVisibleChange;

multipleInputValue;

singleInputValue;

install(): void {
const { loading, suffixIcon } = this.props;
const { loading, suffixIcon, multiple } = this.props;
this.commonInputProps = {
...pick(this.props, COMMON_PROPERTIES),
suffixIcon: loading ? <t-loading loading size="small" /> : suffixIcon,
Expand All @@ -73,20 +124,30 @@ class SelectInput extends Component<SelectInputProps> {
const { innerPopupVisible, tOverlayInnerStyle, onInnerPopupVisibleChange } = useOverlayInnerStyle(
this.props,
{
// afterHidePopup: this.onInnerBlur,
afterHidePopup: this.onInnerBlur.bind(this),
},
this,
);
this.tOverlayInnerStyle = tOverlayInnerStyle;
this.innerPopupVisible = innerPopupVisible;
this.onInnerPopupVisibleChange = onInnerPopupVisibleChange;

if (multiple) {
this.multipleInputValue = this.props.inputValue || this.props.defaultInputValue;
} else {
this.singleInputValue = this.props.inputValue || this.props.defaultInputValue;
}
}

// onInnerBlur(ctx: PopupVisibleChangeContext) {
// const inputValue = this.props.multiple ? multipleInputValue : singleInputValue;
// const params: Parameters<TdSelectInputProps['onBlur']>[1] = { e: ctx.e, inputValue };
// this.props.onBlur?.(this.props.value, params);
// }
updateValue = (val, key: 'multipleInputValue' | 'singleInputValue') => {
this[key] = val;
};

onInnerBlur(ctx: PopupVisibleChangeContext) {
const inputValue = this.props.multiple ? this.multipleInputValue : this.singleInputValue;
const params: Parameters<TdSelectInputProps['onBlur']>[1] = { e: ctx.e, inputValue };
this.props.onBlur?.(this.props.value, params);
}

render(props: SelectInputProps | OmiProps<SelectInputProps, any>) {
const { multiple, value, popupVisible, popupProps, borderless, disabled } = props;
Expand All @@ -95,7 +156,7 @@ class SelectInput extends Component<SelectInputProps> {
const visibleProps = { visible: popupVisible ?? this.innerPopupVisible };

const popupClasses = classNames([
props.innerClass,
!props.tips ? props.innerClass : '',
`${this.classPrefix}-select-input`,
{
[`${this.classPrefix}-select-input--borderless`]: borderless,
Expand All @@ -106,7 +167,7 @@ class SelectInput extends Component<SelectInputProps> {
]);

const mainContent = (
<div className={popupClasses} style={props.innerStyle}>
<div className={popupClasses} style={!props.tips ? props.innerStyle : {}}>
<t-popup
trigger={popupProps?.trigger || 'click'}
placement="bottom-left"
Expand All @@ -124,12 +185,14 @@ class SelectInput extends Component<SelectInputProps> {
{...props}
commonInputProps={this.commonInputProps}
popupVisible={visibleProps.visible}
onUpdateValue={this.updateValue}
/>
) : (
<t-select-input-single
{...props}
commonInputProps={this.commonInputProps}
popupVisible={visibleProps.visible}
onUpdateValue={this.updateValue}
/>
)}
</t-popup>
Expand All @@ -141,7 +204,11 @@ class SelectInput extends Component<SelectInputProps> {
}

return (
<div ref={this.selectInputWrapRef} className={`${this.classPrefix}-select-input__wrap`}>
<div
ref={this.selectInputWrapRef}
className={classNames(`${this.classPrefix}-select-input__wrap`, props.innerClass)}
style={props.innerStyle}
>
{mainContent}
{props.tips && (
<div
Expand Down
Loading

0 comments on commit 8f03ef0

Please sign in to comment.