From 8658806e3f63c07148c8309283a4221d202ff576 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Wed, 8 Feb 2023 11:04:16 +0800 Subject: [PATCH] feat: input add disabled --- components/_util/type.ts | 3 +++ components/config-provider/DisabledContext.ts | 2 +- components/input/ClearableLabeledInput.tsx | 21 ++++++++++--------- components/input/Group.tsx | 18 +++------------- components/input/Input.tsx | 4 ++++ components/input/Search.tsx | 2 +- components/input/TextArea.tsx | 13 ++++++++---- components/input/index.en-US.md | 2 +- components/input/index.zh-CN.md | 2 +- components/input/inputProps.ts | 5 +++-- .../input/style/{index.tsx => index.ts} | 0 components/vc-input/inputProps.ts | 2 +- 12 files changed, 38 insertions(+), 36 deletions(-) rename components/input/style/{index.tsx => index.ts} (100%) diff --git a/components/_util/type.ts b/components/_util/type.ts index 057bbbba3..25f5fc329 100644 --- a/components/_util/type.ts +++ b/components/_util/type.ts @@ -62,6 +62,9 @@ export function functionType {}>(defaultVal?: any) { export function anyType() { return { validator: () => true } as unknown as { type: PropType }; } +export function vNodeType() { + return { validator: () => true } as unknown as { type: PropType }; +} export function stringType(defaultVal?: string) { return { type: String as unknown as PropType, default: defaultVal as T }; diff --git a/components/config-provider/DisabledContext.ts b/components/config-provider/DisabledContext.ts index a59ebaa6b..7f5388661 100644 --- a/components/config-provider/DisabledContext.ts +++ b/components/config-provider/DisabledContext.ts @@ -5,7 +5,7 @@ export type DisabledType = boolean | undefined; const DisabledContextKey: InjectionKey> = Symbol('DisabledContextKey'); export const useInjectDisabled = () => { - return inject(DisabledContextKey, ref(undefined)); + return inject(DisabledContextKey, ref(undefined)); }; export const useProviderDisabled = (disabled: Ref) => { const parentDisabled = useInjectDisabled(); diff --git a/components/input/ClearableLabeledInput.tsx b/components/input/ClearableLabeledInput.tsx index 072019dd2..3728a249f 100644 --- a/components/input/ClearableLabeledInput.tsx +++ b/components/input/ClearableLabeledInput.tsx @@ -4,7 +4,8 @@ import PropTypes from '../_util/vue-types'; import { cloneElement } from '../_util/vnode'; import type { CSSProperties, PropType, VNode } from 'vue'; import { defineComponent } from 'vue'; -import { tuple } from '../_util/type'; +import type { VueNode } from '../_util/type'; +import { anyType, tuple } from '../_util/type'; import type { Direction, SizeType } from '../config-provider'; import type { MouseEventHandler } from '../_util/EventInterface'; import { hasAddon } from './util'; @@ -12,7 +13,7 @@ import { FormItemInputContext } from '../form/FormItemContext'; import type { InputStatus } from '../_util/statusUtils'; import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; -const ClearableInputType = ['text', 'input']; +const ClearableInputType = ['text', 'input'] as const; export default defineComponent({ compatConfig: { MODE: 3 }, @@ -21,18 +22,18 @@ export default defineComponent({ props: { prefixCls: String, inputType: PropTypes.oneOf(tuple('text', 'input')), - value: PropTypes.any, - defaultValue: PropTypes.any, + value: anyType(), + defaultValue: anyType(), allowClear: { type: Boolean, default: undefined }, - element: PropTypes.any, + element: anyType(), handleReset: Function as PropType, disabled: { type: Boolean, default: undefined }, direction: { type: String as PropType }, size: { type: String as PropType }, - suffix: PropTypes.any, - prefix: PropTypes.any, - addonBefore: PropTypes.any, - addonAfter: PropTypes.any, + suffix: anyType(), + prefix: anyType(), + addonBefore: anyType(), + addonAfter: anyType(), readonly: { type: Boolean, default: undefined }, focused: { type: Boolean, default: undefined }, bordered: { type: Boolean, default: true }, @@ -114,7 +115,7 @@ export default defineComponent({ return () => { const { prefixCls, inputType, element = slots.element?.() } = props; if (inputType === ClearableInputType[0]) { - return renderTextAreaWithClearIcon(prefixCls, element); + return renderTextAreaWithClearIcon(prefixCls, element as VNode); } return null; }; diff --git a/components/input/Group.tsx b/components/input/Group.tsx index 33230554e..b196463f8 100644 --- a/components/input/Group.tsx +++ b/components/input/Group.tsx @@ -2,7 +2,6 @@ import type { PropType } from 'vue'; import { computed, defineComponent } from 'vue'; import type { SizeType } from '../config-provider'; import { FormItemInputContext } from '../form/FormItemContext'; -import type { FocusEventHandler, MouseEventHandler } from '../_util/EventInterface'; import useConfigInject from '../config-provider/hooks/useConfigInject'; import classNames from '../_util/classNames'; @@ -17,20 +16,16 @@ export default defineComponent({ prefixCls: String, size: { type: String as PropType }, compact: { type: Boolean, default: undefined }, - onMouseenter: { type: Function as PropType }, - onMouseleave: { type: Function as PropType }, - onFocus: { type: Function as PropType }, - onBlur: { type: Function as PropType }, }, setup(props, { slots, attrs }) { - const { prefixCls, direction } = useConfigInject('input-group', props); + const { prefixCls, direction, getPrefixCls } = useConfigInject('input-group', props); const formItemInputContext = FormItemInputContext.useInject(); FormItemInputContext.useProvide(formItemInputContext, { isFormItemInput: false, }); // style - const { prefixCls: inputPrefixCls } = useConfigInject('input', props); + const inputPrefixCls = computed(() => getPrefixCls('input')); const [wrapSSR, hashId] = useStyle(inputPrefixCls); const cls = computed(() => { @@ -46,14 +41,7 @@ export default defineComponent({ }); return () => { return wrapSSR( - + {slots.default?.()} , ); diff --git a/components/input/Input.tsx b/components/input/Input.tsx index a4eeb20bd..1a4d28ef5 100644 --- a/components/input/Input.tsx +++ b/components/input/Input.tsx @@ -16,6 +16,7 @@ import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled'; // CSSINJS import useStyle from './style'; +import { useInjectDisabled } from '../config-provider/DisabledContext'; export default defineComponent({ compatConfig: { MODE: 3 }, @@ -32,6 +33,8 @@ export default defineComponent({ // Style const [wrapSSR, hashId] = useStyle(prefixCls); + const disabled = useInjectDisabled(); + const focus = (option?: InputFocusOptions) => { inputRef.value?.focus(option); }; @@ -129,6 +132,7 @@ export default defineComponent({ {...omit(rest, ['onUpdate:value', 'onChange', 'onInput'])} onChange={triggerChange} id={id} + disabled={props.disabled ?? disabled.value} ref={inputRef} prefixCls={prefixClsValue} autocomplete={autocomplete.value} diff --git a/components/input/Search.tsx b/components/input/Search.tsx index fec128af1..4ec8fe3a9 100644 --- a/components/input/Search.tsx +++ b/components/input/Search.tsx @@ -64,7 +64,7 @@ export default defineComponent({ }; const onPressEnter = (e: KeyboardEvent) => { - if (composedRef.value) { + if (composedRef.value || props.loading) { return; } onSearch(e); diff --git a/components/input/TextArea.tsx b/components/input/TextArea.tsx index 1863c6882..e0bf37ce8 100644 --- a/components/input/TextArea.tsx +++ b/components/input/TextArea.tsx @@ -23,6 +23,7 @@ import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; // CSSINJS import useStyle from './style'; +import { useInjectDisabled } from '../config-provider/DisabledContext'; function fixEmojiLength(value: string, maxLength: number) { return [...(value || '')].slice(0, maxLength).join(''); @@ -64,7 +65,7 @@ export default defineComponent({ // Style const [wrapSSR, hashId] = useStyle(prefixCls); - + const disabled = useInjectDisabled(); const showCount = computed(() => { return (props.showCount as any) === '' || props.showCount || false; }); @@ -191,12 +192,11 @@ export default defineComponent({ setValue(triggerValue); }; const renderTextArea = () => { - const { style, class: customClass } = attrs; + const { class: customClass } = attrs; const { bordered = true } = props; const resizeProps = { ...omit(props, ['allowClear']), ...attrs, - style: showCount.value ? {} : style, class: [ { [`${prefixCls.value}-borderless`]: !bordered, @@ -261,6 +261,7 @@ export default defineComponent({ bordered, style: showCount.value ? undefined : style, hashId: hashId.value, + disabled: props.disabled ?? disabled.value, }; let textareaNode = ( @@ -276,7 +277,11 @@ export default defineComponent({ const valueLength = [...mergedValue.value].length; let dataCount: VueNode = ''; if (typeof showCount.value === 'object') { - dataCount = showCount.value.formatter({ count: valueLength, maxlength }); + dataCount = showCount.value.formatter({ + value: mergedValue.value, + count: valueLength, + maxlength, + }); } else { dataCount = `${valueLength}${hasMaxLength.value ? ` / ${maxlength}` : ''}`; } diff --git a/components/input/index.en-US.md b/components/input/index.en-US.md index 88b4c51fb..8872b66e4 100644 --- a/components/input/index.en-US.md +++ b/components/input/index.en-US.md @@ -2,7 +2,7 @@ category: Components type: Data Entry title: Input -cover: https://gw.alipayobjects.com/zos/alicdn/xS9YEJhfe/Input.svg +cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Y3R0RowXHlAAAAAAAAAAAAAADrJ8AQ/original --- A basic widget for getting the user input is a text field. Keyboard and mouse can be used for providing or changing data. diff --git a/components/input/index.zh-CN.md b/components/input/index.zh-CN.md index fb798e1f1..8be538455 100644 --- a/components/input/index.zh-CN.md +++ b/components/input/index.zh-CN.md @@ -3,7 +3,7 @@ category: Components type: 数据录入 title: Input subtitle: 输入框 -cover: https://gw.alipayobjects.com/zos/alicdn/xS9YEJhfe/Input.svg +cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Y3R0RowXHlAAAAAAAAAAAAAADrJ8AQ/original --- 通过鼠标或键盘输入内容,是最基础的表单域的包装。 diff --git a/components/input/inputProps.ts b/components/input/inputProps.ts index 9251c5d5f..9c6f4ac3f 100644 --- a/components/input/inputProps.ts +++ b/components/input/inputProps.ts @@ -1,6 +1,7 @@ import type { ExtractPropTypes, PropType } from 'vue'; import omit from '../_util/omit'; import type { VueNode } from '../_util/type'; +import { eventType } from '../_util/type'; import type { CompositionEventHandler } from '../_util/EventInterface'; import { inputProps as vcInputProps } from '../vc-input/inputProps'; @@ -29,8 +30,8 @@ const textAreaProps = () => ({ autosize: { type: [Boolean, Object] as PropType, default: undefined }, autoSize: { type: [Boolean, Object] as PropType, default: undefined }, onResize: { type: Function as PropType<(size: { width: number; height: number }) => void> }, - onCompositionstart: Function as PropType, - onCompositionend: Function as PropType, + onCompositionstart: eventType(), + onCompositionend: eventType(), valueModifiers: Object, }); diff --git a/components/input/style/index.tsx b/components/input/style/index.ts similarity index 100% rename from components/input/style/index.tsx rename to components/input/style/index.ts diff --git a/components/vc-input/inputProps.ts b/components/vc-input/inputProps.ts index 1330d15cd..b883373c4 100644 --- a/components/vc-input/inputProps.ts +++ b/components/vc-input/inputProps.ts @@ -107,7 +107,7 @@ export const inputProps = () => ({ export type InputProps = Partial>>; export interface ShowCountProps { - formatter: (args: { count: number; maxlength?: number }) => VueNode; + formatter: (args: { count: number; maxlength?: number; value?: string }) => VueNode; } export interface InputRef {