feat: input add disabled

pull/6245/head
tangjinzhou 2023-02-08 11:04:16 +08:00
parent 4f3ce35e74
commit 8658806e3f
12 changed files with 38 additions and 36 deletions

View File

@ -62,6 +62,9 @@ export function functionType<T = () => {}>(defaultVal?: any) {
export function anyType<T = any>() { export function anyType<T = any>() {
return { validator: () => true } as unknown as { type: PropType<T> }; return { validator: () => true } as unknown as { type: PropType<T> };
} }
export function vNodeType<T = VueNode>() {
return { validator: () => true } as unknown as { type: PropType<T> };
}
export function stringType<T extends string = string>(defaultVal?: string) { export function stringType<T extends string = string>(defaultVal?: string) {
return { type: String as unknown as PropType<T>, default: defaultVal as T }; return { type: String as unknown as PropType<T>, default: defaultVal as T };

View File

@ -5,7 +5,7 @@ export type DisabledType = boolean | undefined;
const DisabledContextKey: InjectionKey<Ref<DisabledType>> = Symbol('DisabledContextKey'); const DisabledContextKey: InjectionKey<Ref<DisabledType>> = Symbol('DisabledContextKey');
export const useInjectDisabled = () => { export const useInjectDisabled = () => {
return inject(DisabledContextKey, ref(undefined)); return inject(DisabledContextKey, ref<DisabledType>(undefined));
}; };
export const useProviderDisabled = (disabled: Ref<DisabledType>) => { export const useProviderDisabled = (disabled: Ref<DisabledType>) => {
const parentDisabled = useInjectDisabled(); const parentDisabled = useInjectDisabled();

View File

@ -4,7 +4,8 @@ import PropTypes from '../_util/vue-types';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import type { CSSProperties, PropType, VNode } from 'vue'; import type { CSSProperties, PropType, VNode } from 'vue';
import { defineComponent } 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 { Direction, SizeType } from '../config-provider';
import type { MouseEventHandler } from '../_util/EventInterface'; import type { MouseEventHandler } from '../_util/EventInterface';
import { hasAddon } from './util'; import { hasAddon } from './util';
@ -12,7 +13,7 @@ import { FormItemInputContext } from '../form/FormItemContext';
import type { InputStatus } from '../_util/statusUtils'; import type { InputStatus } from '../_util/statusUtils';
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
const ClearableInputType = ['text', 'input']; const ClearableInputType = ['text', 'input'] as const;
export default defineComponent({ export default defineComponent({
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
@ -21,18 +22,18 @@ export default defineComponent({
props: { props: {
prefixCls: String, prefixCls: String,
inputType: PropTypes.oneOf(tuple('text', 'input')), inputType: PropTypes.oneOf(tuple('text', 'input')),
value: PropTypes.any, value: anyType<VueNode>(),
defaultValue: PropTypes.any, defaultValue: anyType<VueNode>(),
allowClear: { type: Boolean, default: undefined }, allowClear: { type: Boolean, default: undefined },
element: PropTypes.any, element: anyType<VueNode>(),
handleReset: Function as PropType<MouseEventHandler>, handleReset: Function as PropType<MouseEventHandler>,
disabled: { type: Boolean, default: undefined }, disabled: { type: Boolean, default: undefined },
direction: { type: String as PropType<Direction> }, direction: { type: String as PropType<Direction> },
size: { type: String as PropType<SizeType> }, size: { type: String as PropType<SizeType> },
suffix: PropTypes.any, suffix: anyType<VueNode>(),
prefix: PropTypes.any, prefix: anyType<VueNode>(),
addonBefore: PropTypes.any, addonBefore: anyType<VueNode>(),
addonAfter: PropTypes.any, addonAfter: anyType<VueNode>(),
readonly: { type: Boolean, default: undefined }, readonly: { type: Boolean, default: undefined },
focused: { type: Boolean, default: undefined }, focused: { type: Boolean, default: undefined },
bordered: { type: Boolean, default: true }, bordered: { type: Boolean, default: true },
@ -114,7 +115,7 @@ export default defineComponent({
return () => { return () => {
const { prefixCls, inputType, element = slots.element?.() } = props; const { prefixCls, inputType, element = slots.element?.() } = props;
if (inputType === ClearableInputType[0]) { if (inputType === ClearableInputType[0]) {
return renderTextAreaWithClearIcon(prefixCls, element); return renderTextAreaWithClearIcon(prefixCls, element as VNode);
} }
return null; return null;
}; };

View File

@ -2,7 +2,6 @@ import type { PropType } from 'vue';
import { computed, defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import type { SizeType } from '../config-provider'; import type { SizeType } from '../config-provider';
import { FormItemInputContext } from '../form/FormItemContext'; import { FormItemInputContext } from '../form/FormItemContext';
import type { FocusEventHandler, MouseEventHandler } from '../_util/EventInterface';
import useConfigInject from '../config-provider/hooks/useConfigInject'; import useConfigInject from '../config-provider/hooks/useConfigInject';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
@ -17,20 +16,16 @@ export default defineComponent({
prefixCls: String, prefixCls: String,
size: { type: String as PropType<SizeType> }, size: { type: String as PropType<SizeType> },
compact: { type: Boolean, default: undefined }, compact: { type: Boolean, default: undefined },
onMouseenter: { type: Function as PropType<MouseEventHandler> },
onMouseleave: { type: Function as PropType<MouseEventHandler> },
onFocus: { type: Function as PropType<FocusEventHandler> },
onBlur: { type: Function as PropType<FocusEventHandler> },
}, },
setup(props, { slots, attrs }) { setup(props, { slots, attrs }) {
const { prefixCls, direction } = useConfigInject('input-group', props); const { prefixCls, direction, getPrefixCls } = useConfigInject('input-group', props);
const formItemInputContext = FormItemInputContext.useInject(); const formItemInputContext = FormItemInputContext.useInject();
FormItemInputContext.useProvide(formItemInputContext, { FormItemInputContext.useProvide(formItemInputContext, {
isFormItemInput: false, isFormItemInput: false,
}); });
// style // style
const { prefixCls: inputPrefixCls } = useConfigInject('input', props); const inputPrefixCls = computed(() => getPrefixCls('input'));
const [wrapSSR, hashId] = useStyle(inputPrefixCls); const [wrapSSR, hashId] = useStyle(inputPrefixCls);
const cls = computed(() => { const cls = computed(() => {
@ -46,14 +41,7 @@ export default defineComponent({
}); });
return () => { return () => {
return wrapSSR( return wrapSSR(
<span <span {...attrs} class={classNames(cls.value, attrs.class)}>
{...attrs}
class={classNames(cls.value, attrs.class)}
onMouseenter={props.onMouseenter}
onMouseleave={props.onMouseleave}
onFocus={props.onFocus}
onBlur={props.onBlur}
>
{slots.default?.()} {slots.default?.()}
</span>, </span>,
); );

View File

@ -16,6 +16,7 @@ import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
// CSSINJS // CSSINJS
import useStyle from './style'; import useStyle from './style';
import { useInjectDisabled } from '../config-provider/DisabledContext';
export default defineComponent({ export default defineComponent({
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
@ -32,6 +33,8 @@ export default defineComponent({
// Style // Style
const [wrapSSR, hashId] = useStyle(prefixCls); const [wrapSSR, hashId] = useStyle(prefixCls);
const disabled = useInjectDisabled();
const focus = (option?: InputFocusOptions) => { const focus = (option?: InputFocusOptions) => {
inputRef.value?.focus(option); inputRef.value?.focus(option);
}; };
@ -129,6 +132,7 @@ export default defineComponent({
{...omit(rest, ['onUpdate:value', 'onChange', 'onInput'])} {...omit(rest, ['onUpdate:value', 'onChange', 'onInput'])}
onChange={triggerChange} onChange={triggerChange}
id={id} id={id}
disabled={props.disabled ?? disabled.value}
ref={inputRef} ref={inputRef}
prefixCls={prefixClsValue} prefixCls={prefixClsValue}
autocomplete={autocomplete.value} autocomplete={autocomplete.value}

View File

@ -64,7 +64,7 @@ export default defineComponent({
}; };
const onPressEnter = (e: KeyboardEvent) => { const onPressEnter = (e: KeyboardEvent) => {
if (composedRef.value) { if (composedRef.value || props.loading) {
return; return;
} }
onSearch(e); onSearch(e);

View File

@ -23,6 +23,7 @@ import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
// CSSINJS // CSSINJS
import useStyle from './style'; import useStyle from './style';
import { useInjectDisabled } from '../config-provider/DisabledContext';
function fixEmojiLength(value: string, maxLength: number) { function fixEmojiLength(value: string, maxLength: number) {
return [...(value || '')].slice(0, maxLength).join(''); return [...(value || '')].slice(0, maxLength).join('');
@ -64,7 +65,7 @@ export default defineComponent({
// Style // Style
const [wrapSSR, hashId] = useStyle(prefixCls); const [wrapSSR, hashId] = useStyle(prefixCls);
const disabled = useInjectDisabled();
const showCount = computed(() => { const showCount = computed(() => {
return (props.showCount as any) === '' || props.showCount || false; return (props.showCount as any) === '' || props.showCount || false;
}); });
@ -191,12 +192,11 @@ export default defineComponent({
setValue(triggerValue); setValue(triggerValue);
}; };
const renderTextArea = () => { const renderTextArea = () => {
const { style, class: customClass } = attrs; const { class: customClass } = attrs;
const { bordered = true } = props; const { bordered = true } = props;
const resizeProps = { const resizeProps = {
...omit(props, ['allowClear']), ...omit(props, ['allowClear']),
...attrs, ...attrs,
style: showCount.value ? {} : style,
class: [ class: [
{ {
[`${prefixCls.value}-borderless`]: !bordered, [`${prefixCls.value}-borderless`]: !bordered,
@ -261,6 +261,7 @@ export default defineComponent({
bordered, bordered,
style: showCount.value ? undefined : style, style: showCount.value ? undefined : style,
hashId: hashId.value, hashId: hashId.value,
disabled: props.disabled ?? disabled.value,
}; };
let textareaNode = ( let textareaNode = (
@ -276,7 +277,11 @@ export default defineComponent({
const valueLength = [...mergedValue.value].length; const valueLength = [...mergedValue.value].length;
let dataCount: VueNode = ''; let dataCount: VueNode = '';
if (typeof showCount.value === 'object') { if (typeof showCount.value === 'object') {
dataCount = showCount.value.formatter({ count: valueLength, maxlength }); dataCount = showCount.value.formatter({
value: mergedValue.value,
count: valueLength,
maxlength,
});
} else { } else {
dataCount = `${valueLength}${hasMaxLength.value ? ` / ${maxlength}` : ''}`; dataCount = `${valueLength}${hasMaxLength.value ? ` / ${maxlength}` : ''}`;
} }

View File

@ -2,7 +2,7 @@
category: Components category: Components
type: Data Entry type: Data Entry
title: Input 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. A basic widget for getting the user input is a text field. Keyboard and mouse can be used for providing or changing data.

View File

@ -3,7 +3,7 @@ category: Components
type: 数据录入 type: 数据录入
title: Input title: Input
subtitle: 输入框 subtitle: 输入框
cover: https://gw.alipayobjects.com/zos/alicdn/xS9YEJhfe/Input.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Y3R0RowXHlAAAAAAAAAAAAAADrJ8AQ/original
--- ---
通过鼠标或键盘输入内容,是最基础的表单域的包装。 通过鼠标或键盘输入内容,是最基础的表单域的包装。

View File

@ -1,6 +1,7 @@
import type { ExtractPropTypes, PropType } from 'vue'; import type { ExtractPropTypes, PropType } from 'vue';
import omit from '../_util/omit'; import omit from '../_util/omit';
import type { VueNode } from '../_util/type'; import type { VueNode } from '../_util/type';
import { eventType } from '../_util/type';
import type { CompositionEventHandler } from '../_util/EventInterface'; import type { CompositionEventHandler } from '../_util/EventInterface';
import { inputProps as vcInputProps } from '../vc-input/inputProps'; import { inputProps as vcInputProps } from '../vc-input/inputProps';
@ -29,8 +30,8 @@ const textAreaProps = () => ({
autosize: { type: [Boolean, Object] as PropType<boolean | AutoSizeType>, default: undefined }, autosize: { type: [Boolean, Object] as PropType<boolean | AutoSizeType>, default: undefined },
autoSize: { type: [Boolean, Object] as PropType<boolean | AutoSizeType>, default: undefined }, autoSize: { type: [Boolean, Object] as PropType<boolean | AutoSizeType>, default: undefined },
onResize: { type: Function as PropType<(size: { width: number; height: number }) => void> }, onResize: { type: Function as PropType<(size: { width: number; height: number }) => void> },
onCompositionstart: Function as PropType<CompositionEventHandler>, onCompositionstart: eventType<CompositionEventHandler>(),
onCompositionend: Function as PropType<CompositionEventHandler>, onCompositionend: eventType<CompositionEventHandler>(),
valueModifiers: Object, valueModifiers: Object,
}); });

View File

@ -107,7 +107,7 @@ export const inputProps = () => ({
export type InputProps = Partial<ExtractPropTypes<ReturnType<typeof inputProps>>>; export type InputProps = Partial<ExtractPropTypes<ReturnType<typeof inputProps>>>;
export interface ShowCountProps { export interface ShowCountProps {
formatter: (args: { count: number; maxlength?: number }) => VueNode; formatter: (args: { count: number; maxlength?: number; value?: string }) => VueNode;
} }
export interface InputRef { export interface InputRef {