Skip to content

Commit

Permalink
feat(input): support clearTrigger
Browse files Browse the repository at this point in the history
  • Loading branch information
liweijie0812 committed Jul 1, 2024
1 parent 2a6f692 commit 116d103
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 27 deletions.
3 changes: 2 additions & 1 deletion src/input/input.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ allowInputOverMax | Boolean | false | allow to continue input on value length is
autocomplete | String | undefined | attribute of input element, [see here](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) | N
autofocus | Boolean | false | autofocus on first rendered | N
borderless | Boolean | false | input without border | N
clearTrigger | String | always | show clear icon, clicked to clear input value。options: always / focus | N
clearable | Boolean | false | show clear icon, clicked to clear input value | N
disabled | Boolean | undefined | make input to be disabled | N
format | Function | - | input value formatter, `type=number` does not work. if you need to format number, `InputNumber` Component might be better。Typescript:`InputFormatType` `type InputFormatType = (value: InputValue) => string`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/input/type.ts) | N
Expand All @@ -22,7 +23,7 @@ maxlength | String / Number | - | \- | N
name | String | - | \- | N
placeholder | String | undefined | \- | N
prefixIcon | Slot / Function | - | Typescript:`TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
readonly | Boolean | false | \- | N
readonly | Boolean | undefined | \- | N
size | String | small | `deprecated`。options: small/medium。Typescript:`'medium' \| 'small'` | N
spellCheck | Boolean | false | attribute of input element, [see here](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/spellcheck) | N
status | String | undefined | options: default/success/warning/error | N
Expand Down
3 changes: 2 additions & 1 deletion src/input/input.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ allowInputOverMax | Boolean | false | 超出 `maxlength` 或 `maxcharacter` 之
autocomplete | String | undefined | 是否开启自动填充功能,HTML5 原生属性,[点击查看详情](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) | N
autofocus | Boolean | false | 自动聚焦 | N
borderless | Boolean | false | 是否开启无边框模式 | N
clearTrigger | String | always | 清空图标触发方式,仅在输入框有值时有效。可选项:always / focus | N
clearable | Boolean | false | 是否可清空 | N
disabled | Boolean | undefined | 是否禁用输入框 | N
format | Function | - | 【开发中】指定输入框展示值的格式。TS 类型:`InputFormatType` `type InputFormatType = (value: InputValue) => string`[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/input/type.ts) | N
Expand All @@ -21,7 +22,7 @@ maxlength | String / Number | - | 用户最多可以输入的文本长度,一
name | String | - | 名称 | N
placeholder | String | undefined | 占位符 | N
prefixIcon | Slot / Function | - | 组件前置图标。TS 类型:`TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
readonly | Boolean | false | 只读状态 | N
readonly | Boolean | undefined | 只读状态 | N
size | String | small | 已废弃。输入框尺寸。可选项:small/medium。TS 类型:`'medium' \| 'small'` | N
spellCheck | Boolean | false | 是否开启拼写检查,HTML5 原生属性,[点击查看详情](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/spellcheck) | N
status | String | undefined | 输入框状态。默认情况会由组件内部根据实际情况呈现,如果文本过长引起的状态变化。可选项:default/success/warning/error | N
Expand Down
61 changes: 37 additions & 24 deletions src/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ export default defineComponent({
const isDisabled = useFormDisabled();

const inputRef = ref();
const { autofocus } = toRefs(props);
const [innerValue] = useDefault<string, TdInputProps>(props, context.emit, 'value', 'change');

const status = props.status || 'default';
const renderType = ref(props.type);
const { focused } = useFocus(inputRef, { initialValue: props.autofocus });
const focused = ref(false);

const inputClasses = computed(() => [
`${inputClass.value}__control`,
Expand All @@ -64,6 +63,12 @@ export default defineComponent({
[`${inputClass.value}--border`]: !props.borderless,
},
]);
const showClearable = computed(() => {
if (props.clearable && innerValue.value && innerValue.value.length > 0) {
return props.clearTrigger === 'always' || (props.clearTrigger === 'focus' && focused.value);
}
return false;
});

const setInputValue = (v: InputValue = '') => {
const input = inputRef.value as HTMLInputElement;
Expand Down Expand Up @@ -101,25 +106,26 @@ export default defineComponent({
};

const focus = () => {
focused.value = true;
inputRef.value?.focus();
};

const blur = () => {
focused.value = false;
// inputRef.value?.blur();
inputRef.value?.blur();
};

extendAPI({ focus, blur });

const handleClear = (e: MouseEvent) => {
const handleClear = (e: TouchEvent) => {
innerValue.value = '';
focused.value = true;
props.onClear?.({ e });
props.onClear?.({ e: e as unknown as MouseEvent });
};
const handleFocus = (e: FocusEvent) => {
focused.value = true;
props.onFocus?.(innerValue.value, { e });
};
const handleBlur = (e: FocusEvent) => {
focused.value = false;
props.onBlur?.(innerValue.value, { e });
};

Expand All @@ -131,13 +137,17 @@ export default defineComponent({
renderType.value = renderType.value === 'password' ? 'text' : 'password';
};

watch(autofocus, (autofocus, prevAutofocus) => {
if (autofocus === true) {
nextTick(() => {
focused.value = true;
});
}
});
watch(
() => props.autofocus,
(v) => {
if (v === true) {
nextTick(() => {
focused.value = true;
});
}
},
{ immediate: true },
);

watch(
() => props.type,
Expand All @@ -146,6 +156,18 @@ export default defineComponent({
},
{ immediate: true },
);
const readerClearable = () => {
if (showClearable.value) {
// pc端仅mousedown事件触发早于blur,移动端touch相关事件触发均早于blur
return (
<div class={`${inputClass.value}__wrap--clearable-icon`} onTouchend={handleClear}>
<TCloseCircleFilledIcon />
</div>
);
}

return null;
};

return () => {
const readerPrefix = () => {
Expand All @@ -159,16 +181,7 @@ export default defineComponent({
</div>
);
};
const readerClearable = () => {
if (props.clearable && innerValue.value && innerValue.value.length > 0) {
return (
<div class={`${inputClass.value}__wrap--clearable-icon`} onClick={handleClear}>
<TCloseCircleFilledIcon />
</div>
);
}
return null;
};

const readerSuffix = () => {
const suffix = readerTNodeJSX('suffix');
if (!suffix) {
Expand Down
14 changes: 13 additions & 1 deletion src/input/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export default {
autofocus: Boolean,
/** 是否开启无边框模式 */
borderless: Boolean,
/** 清空图标触发方式,仅在输入框有值时有效 */
clearTrigger: {
type: String as PropType<TdInputProps['clearTrigger']>,
default: 'always' as TdInputProps['clearTrigger'],
validator(val: TdInputProps['clearTrigger']): boolean {
if (!val) return true;
return ['always', 'focus'].includes(val);
},
},
/** 是否可清空 */
clearable: Boolean,
/** 是否禁用输入框 */
Expand Down Expand Up @@ -75,7 +84,10 @@ export default {
type: Function as PropType<TdInputProps['prefixIcon']>,
},
/** 只读状态 */
readonly: Boolean,
readonly: {
type: Boolean,
default: undefined,
},
/** 是否开启拼写检查,HTML5 原生属性,[点击查看详情](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/spellcheck) */
spellCheck: Boolean,
/** 输入框状态。默认情况会由组件内部根据实际情况呈现,如果文本过长引起的状态变化 */
Expand Down
5 changes: 5 additions & 0 deletions src/input/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export interface TdInputProps {
* @default false
*/
borderless?: boolean;
/**
* 清空图标触发方式,仅在输入框有值时有效
* @default always
*/
clearTrigger?: 'always' | 'focus';
/**
* 是否可清空
* @default false
Expand Down

0 comments on commit 116d103

Please sign in to comment.