feat: inputnumber add status & upIcon & downIcon
							parent
							
								
									093fa555ba
								
							
						
					
					
						commit
						6e41fbd01f
					
				| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
<docs>
 | 
			
		||||
---
 | 
			
		||||
order: 99
 | 
			
		||||
title:
 | 
			
		||||
  zh-CN: 图标按钮
 | 
			
		||||
  en-US: Icon
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## zh-CN
 | 
			
		||||
 | 
			
		||||
使用 `upIcon` `downIcon` 插槽自定义图标。
 | 
			
		||||
 | 
			
		||||
## en-US
 | 
			
		||||
 | 
			
		||||
use `upIcon` `downIcon` custom icon
 | 
			
		||||
 | 
			
		||||
</docs>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <a-input-number id="inputNumber" v-model:value="value" :min="1" :max="10">
 | 
			
		||||
      <template #upIcon>
 | 
			
		||||
        <ArrowUpOutlined />
 | 
			
		||||
      </template>
 | 
			
		||||
      <template #downIcon>
 | 
			
		||||
        <ArrowDownOutlined />
 | 
			
		||||
      </template>
 | 
			
		||||
    </a-input-number>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent, ref } from 'vue';
 | 
			
		||||
import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons-vue';
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  components: {
 | 
			
		||||
    ArrowUpOutlined,
 | 
			
		||||
    ArrowDownOutlined,
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
    const value = ref<number>(3);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      value,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,8 @@
 | 
			
		|||
    <outOfRangeVue />
 | 
			
		||||
    <borderlessVue />
 | 
			
		||||
    <prefixVue />
 | 
			
		||||
    <statusVue />
 | 
			
		||||
    <iconVue />
 | 
			
		||||
  </demo-sort>
 | 
			
		||||
</template>
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +25,8 @@ import borderlessVue from './borderless.vue';
 | 
			
		|||
import keyboardVue from './keyboard.vue';
 | 
			
		||||
import outOfRangeVue from './out-of-range.vue';
 | 
			
		||||
import prefixVue from './prefix.vue';
 | 
			
		||||
import statusVue from './status.vue';
 | 
			
		||||
import iconVue from './icon.vue';
 | 
			
		||||
import CN from '../index.zh-CN.md';
 | 
			
		||||
import US from '../index.en-US.md';
 | 
			
		||||
import { defineComponent } from 'vue';
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +35,8 @@ export default defineComponent({
 | 
			
		|||
  CN,
 | 
			
		||||
  US,
 | 
			
		||||
  components: {
 | 
			
		||||
    iconVue,
 | 
			
		||||
    statusVue,
 | 
			
		||||
    prefixVue,
 | 
			
		||||
    Basic,
 | 
			
		||||
    Disabled,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
<docs>
 | 
			
		||||
---
 | 
			
		||||
order: 19
 | 
			
		||||
version: 3.3.0
 | 
			
		||||
title:
 | 
			
		||||
  zh-CN: 自定义状态
 | 
			
		||||
  en-US: Status
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## zh-CN
 | 
			
		||||
 | 
			
		||||
使用 `status` 为 InputNumber 添加状态,可选 `error` 或者 `warning`。
 | 
			
		||||
 | 
			
		||||
## en-US
 | 
			
		||||
 | 
			
		||||
Add status to InputNumber with `status`, which could be `error` or `warning`.
 | 
			
		||||
 | 
			
		||||
</docs>
 | 
			
		||||
<template>
 | 
			
		||||
  <a-space direction="vertical" style="width: 100%">
 | 
			
		||||
    <a-input-number status="error" style="width: 100%" />
 | 
			
		||||
    <a-input-number status="warning" style="width: 100%" />
 | 
			
		||||
    <a-input-number status="error" style="width: 100%">
 | 
			
		||||
      <template #prefix><ClockCircleOutlined /></template>
 | 
			
		||||
    </a-input-number>
 | 
			
		||||
    <a-input-number status="warning" style="width: 100%">
 | 
			
		||||
      <template #prefix><ClockCircleOutlined /></template>
 | 
			
		||||
    </a-input-number>
 | 
			
		||||
  </a-space>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { ClockCircleOutlined } from '@ant-design/icons-vue';
 | 
			
		||||
import { defineComponent } from 'vue';
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  components: {
 | 
			
		||||
    ClockCircleOutlined,
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
    return {};
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -31,9 +31,12 @@ When a numeric value needs to be provided.
 | 
			
		|||
| precision | precision of input value | number | - |  |
 | 
			
		||||
| prefix | The prefix icon for the Input | slot | - | 3.0 |
 | 
			
		||||
| size | height of input box | string | - |  |
 | 
			
		||||
| status | Set validation status | 'error' \| 'warning' | - | 3.3.0 |
 | 
			
		||||
| step | The number to which the current value is increased or decreased. It can be an integer or decimal. | number\|string | 1 |  |
 | 
			
		||||
| stringMode | Set value as string to support high precision decimals. Will return string value by `change` | boolean | false | 3.0 |
 | 
			
		||||
| value(v-model) | current value | number |  |  |
 | 
			
		||||
| upIcon | custom up icon | slot | `<UpOutlined />` | 3.3.0 |
 | 
			
		||||
| downIcon | custom up down | slot | `<DownOutlined />` | 3.3.0 |
 | 
			
		||||
 | 
			
		||||
### events
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,22 @@
 | 
			
		|||
import type { PropType, ExtractPropTypes, HTMLAttributes, App } from 'vue';
 | 
			
		||||
import { watch, defineComponent, nextTick, onMounted, ref } from 'vue';
 | 
			
		||||
import { watch, defineComponent, nextTick, onMounted, ref, computed } from 'vue';
 | 
			
		||||
import classNames from '../_util/classNames';
 | 
			
		||||
import UpOutlined from '@ant-design/icons-vue/UpOutlined';
 | 
			
		||||
import DownOutlined from '@ant-design/icons-vue/DownOutlined';
 | 
			
		||||
import VcInputNumber, { inputNumberProps as baseInputNumberProps } from './src/InputNumber';
 | 
			
		||||
import type { SizeType } from '../config-provider';
 | 
			
		||||
import { useInjectFormItemContext } from '../form/FormItemContext';
 | 
			
		||||
import {
 | 
			
		||||
  FormItemInputContext,
 | 
			
		||||
  NoFormStatus,
 | 
			
		||||
  useInjectFormItemContext,
 | 
			
		||||
} from '../form/FormItemContext';
 | 
			
		||||
import useConfigInject from '../_util/hooks/useConfigInject';
 | 
			
		||||
import { cloneElement } from '../_util/vnode';
 | 
			
		||||
import omit from '../_util/omit';
 | 
			
		||||
import PropTypes from '../_util/vue-types';
 | 
			
		||||
import isValidValue from '../_util/isValidValue';
 | 
			
		||||
import type { InputStatus } from '../_util/statusUtils';
 | 
			
		||||
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
 | 
			
		||||
const baseProps = baseInputNumberProps();
 | 
			
		||||
export const inputNumberProps = () => ({
 | 
			
		||||
  ...baseProps,
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +31,7 @@ export const inputNumberProps = () => ({
 | 
			
		|||
  prefix: PropTypes.any,
 | 
			
		||||
  'onUpdate:value': baseProps.onChange,
 | 
			
		||||
  valueModifiers: Object,
 | 
			
		||||
  status: String as PropType<InputStatus>,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export type InputNumberProps = Partial<ExtractPropTypes<ReturnType<typeof inputNumberProps>>>;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +44,8 @@ const InputNumber = defineComponent({
 | 
			
		|||
  slots: ['addonBefore', 'addonAfter', 'prefix'],
 | 
			
		||||
  setup(props, { emit, expose, attrs, slots }) {
 | 
			
		||||
    const formItemContext = useInjectFormItemContext();
 | 
			
		||||
    const formItemInputContext = FormItemInputContext.useInject();
 | 
			
		||||
    const mergedStatus = computed(() => getMergedStatus(formItemInputContext.status, props.status));
 | 
			
		||||
    const { prefixCls, size, direction } = useConfigInject('input-number', props);
 | 
			
		||||
    const mergedValue = ref(props.value === undefined ? props.defaultValue : props.value);
 | 
			
		||||
    const focused = ref(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +93,7 @@ const InputNumber = defineComponent({
 | 
			
		|||
      });
 | 
			
		||||
    });
 | 
			
		||||
    return () => {
 | 
			
		||||
      const { hasFeedback, isFormItemInput, feedbackIcon } = formItemInputContext;
 | 
			
		||||
      const {
 | 
			
		||||
        class: className,
 | 
			
		||||
        bordered,
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +116,9 @@ const InputNumber = defineComponent({
 | 
			
		|||
          [`${preCls}-rtl`]: direction.value === 'rtl',
 | 
			
		||||
          [`${preCls}-readonly`]: readonly,
 | 
			
		||||
          [`${preCls}-borderless`]: !bordered,
 | 
			
		||||
          [`${preCls}-in-form-item`]: isFormItemInput,
 | 
			
		||||
        },
 | 
			
		||||
        getStatusClassNames(preCls, mergedStatus.value),
 | 
			
		||||
        className,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -123,32 +135,42 @@ const InputNumber = defineComponent({
 | 
			
		|||
          onBlur={handleBlur}
 | 
			
		||||
          onFocus={handleFocus}
 | 
			
		||||
          v-slots={{
 | 
			
		||||
            upHandler: () => <UpOutlined class={`${preCls}-handler-up-inner`} />,
 | 
			
		||||
            downHandler: () => <DownOutlined class={`${preCls}-handler-down-inner`} />,
 | 
			
		||||
            upHandler: slots.upIcon
 | 
			
		||||
              ? () => <span class={`${preCls}-handler-up-inner`}>{slots.upIcon()}</span>
 | 
			
		||||
              : () => <UpOutlined class={`${preCls}-handler-up-inner`} />,
 | 
			
		||||
            downHandler: slots.downIcon
 | 
			
		||||
              ? () => <span class={`${preCls}-handler-down-inner`}>{slots.downIcon()}</span>
 | 
			
		||||
              : () => <DownOutlined class={`${preCls}-handler-down-inner`} />,
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      const hasAddon = isValidValue(addonBefore) || isValidValue(addonAfter);
 | 
			
		||||
      if (isValidValue(prefix)) {
 | 
			
		||||
        const affixWrapperCls = classNames(`${preCls}-affix-wrapper`, {
 | 
			
		||||
          [`${preCls}-affix-wrapper-focused`]: focused.value,
 | 
			
		||||
          [`${preCls}-affix-wrapper-disabled`]: props.disabled,
 | 
			
		||||
          [`${preCls}-affix-wrapper-sm`]: size.value === 'small',
 | 
			
		||||
          [`${preCls}-affix-wrapper-lg`]: size.value === 'large',
 | 
			
		||||
          [`${preCls}-affix-wrapper-rtl`]: direction.value === 'rtl',
 | 
			
		||||
          [`${preCls}-affix-wrapper-readonly`]: readonly,
 | 
			
		||||
          [`${preCls}-affix-wrapper-borderless`]: !bordered,
 | 
			
		||||
          // className will go to addon wrapper
 | 
			
		||||
          [`${className}`]: !hasAddon && className,
 | 
			
		||||
        });
 | 
			
		||||
      const hasPrefix = isValidValue(prefix);
 | 
			
		||||
      if (hasPrefix || hasFeedback) {
 | 
			
		||||
        const affixWrapperCls = classNames(
 | 
			
		||||
          `${preCls}-affix-wrapper`,
 | 
			
		||||
          getStatusClassNames(`${preCls}-affix-wrapper`, mergedStatus.value, hasFeedback),
 | 
			
		||||
          {
 | 
			
		||||
            [`${preCls}-affix-wrapper-focused`]: focused.value,
 | 
			
		||||
            [`${preCls}-affix-wrapper-disabled`]: props.disabled,
 | 
			
		||||
            [`${preCls}-affix-wrapper-sm`]: size.value === 'small',
 | 
			
		||||
            [`${preCls}-affix-wrapper-lg`]: size.value === 'large',
 | 
			
		||||
            [`${preCls}-affix-wrapper-rtl`]: direction.value === 'rtl',
 | 
			
		||||
            [`${preCls}-affix-wrapper-readonly`]: readonly,
 | 
			
		||||
            [`${preCls}-affix-wrapper-borderless`]: !bordered,
 | 
			
		||||
            // className will go to addon wrapper
 | 
			
		||||
            [`${className}`]: !hasAddon && className,
 | 
			
		||||
          },
 | 
			
		||||
        );
 | 
			
		||||
        element = (
 | 
			
		||||
          <div
 | 
			
		||||
            class={affixWrapperCls}
 | 
			
		||||
            style={style}
 | 
			
		||||
            onMouseup={() => inputNumberRef.value!.focus()}
 | 
			
		||||
          >
 | 
			
		||||
            <span class={`${preCls}-prefix`}>{prefix}</span>
 | 
			
		||||
            {hasPrefix && <span class={`${preCls}-prefix`}>{prefix}</span>}
 | 
			
		||||
            {element}
 | 
			
		||||
            {hasFeedback && <span class={`${preCls}-suffix`}>{feedbackIcon}</span>}
 | 
			
		||||
          </div>
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -172,14 +194,15 @@ const InputNumber = defineComponent({
 | 
			
		|||
            [`${preCls}-group-wrapper-lg`]: mergeSize === 'large',
 | 
			
		||||
            [`${preCls}-group-wrapper-rtl`]: direction.value === 'rtl',
 | 
			
		||||
          },
 | 
			
		||||
          getStatusClassNames(`${prefixCls}-group-wrapper`, mergedStatus.value, hasFeedback),
 | 
			
		||||
          className,
 | 
			
		||||
        );
 | 
			
		||||
        element = (
 | 
			
		||||
          <div class={mergedGroupClassName} style={style}>
 | 
			
		||||
            <div class={mergedWrapperClassName}>
 | 
			
		||||
              {addonBeforeNode}
 | 
			
		||||
              {addonBeforeNode && <NoFormStatus>{addonBeforeNode}</NoFormStatus>}
 | 
			
		||||
              {element}
 | 
			
		||||
              {addonAfterNode}
 | 
			
		||||
              {addonAfterNode && <NoFormStatus>{addonAfterNode}</NoFormStatus>}
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,8 +34,11 @@ cover: https://gw.alipayobjects.com/zos/alicdn/XOS8qZ0kU/InputNumber.svg
 | 
			
		|||
| precision | 数值精度 | number | - |  |
 | 
			
		||||
| prefix | 带有前缀图标的 input | slot | - | 3.0 |
 | 
			
		||||
| size | 输入框大小 | string | 无 |  |
 | 
			
		||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 |
 | 
			
		||||
| step | 每次改变步数,可以为小数 | number\|string | 1 |  |
 | 
			
		||||
| stringMode | 字符值模式,开启后支持高精度小数。同时 `change` 事件将返回 string 类型 | boolean | false | 3.0 |
 | 
			
		||||
| upIcon | 自定义上箭头图标 | slot | `<UpOutlined />` | 3.3.0 |
 | 
			
		||||
| downIcon | 自定义下箭头图标 | slot | `<DownOutlined />` | 3.3.0 |
 | 
			
		||||
| value(v-model) | 当前值 | number |  |  |
 | 
			
		||||
 | 
			
		||||
### 事件
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
  &-affix-wrapper {
 | 
			
		||||
    .input();
 | 
			
		||||
    // or number handler will cover form status
 | 
			
		||||
    position: static;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    display: inline-flex;
 | 
			
		||||
    width: 90px;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,14 +49,33 @@
 | 
			
		|||
      visibility: hidden;
 | 
			
		||||
      content: '\a0';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .@{ant-prefix}-input-number-handler-wrap {
 | 
			
		||||
      z-index: 2;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-prefix {
 | 
			
		||||
  &-prefix,
 | 
			
		||||
  &-suffix {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex: none;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-prefix {
 | 
			
		||||
    margin-inline-end: @input-affix-margin;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-suffix {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    margin-right: @input-padding-horizontal-base;
 | 
			
		||||
    margin-left: @input-affix-margin;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.@{ant-prefix}-input-number-group-wrapper .@{ant-prefix}-input-number-affix-wrapper {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
@import '../../style/mixins/index';
 | 
			
		||||
@import '../../input/style/mixin';
 | 
			
		||||
@import './affix';
 | 
			
		||||
@import './status';
 | 
			
		||||
 | 
			
		||||
@input-number-prefix-cls: ~'@{ant-prefix}-input-number';
 | 
			
		||||
@form-item-prefix-cls: ~'@{ant-prefix}-form-item';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
@import '../../input/style/mixin';
 | 
			
		||||
 | 
			
		||||
@input-number-prefix-cls: ~'@{ant-prefix}-input-number';
 | 
			
		||||
 | 
			
		||||
@input-number-wrapper-cls: @input-number-prefix-cls, ~'@{input-number-prefix-cls}-affix-wrapper';
 | 
			
		||||
 | 
			
		||||
each(@input-number-wrapper-cls, {
 | 
			
		||||
  .@{value} {
 | 
			
		||||
    &-status-error {
 | 
			
		||||
      .status-color(@value, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline);
 | 
			
		||||
      .status-color-common(@input-number-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-status-warning {
 | 
			
		||||
      .status-color(@value, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
 | 
			
		||||
      .status-color-common(@input-number-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
.@{input-number-prefix-cls}-group-wrapper {
 | 
			
		||||
  &-status-error {
 | 
			
		||||
    .group-status-color(@input-number-prefix-cls, @error-color, @error-color);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-status-warning {
 | 
			
		||||
    .group-status-color(@input-number-prefix-cls, @warning-color, @warning-color);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue