From 078681c23a4158c35ec4e9714601b504ef8c359c Mon Sep 17 00:00:00 2001 From: qmhc <544022268@qq.com> Date: Wed, 5 Apr 2023 20:21:20 +0800 Subject: [PATCH] feat(number-input): add out of range effect for input control --- common/config/src/locale/en-US.ts | 5 +++++ common/config/src/locale/helper.ts | 5 +++++ common/config/src/locale/ta-IN.ts | 5 +++++ common/config/src/locale/zh-CN.ts | 5 +++++ components/number-input/number-input.vue | 15 +++++++++++-- .../number-input/tests/number-input.spec.tsx | 21 +++++++++++++++++++ style/input.scss | 1 + style/number-input.scss | 16 ++++++++++++++ 8 files changed, 71 insertions(+), 2 deletions(-) diff --git a/common/config/src/locale/en-US.ts b/common/config/src/locale/en-US.ts index 39d4de646..65d3f51cb 100644 --- a/common/config/src/locale/en-US.ts +++ b/common/config/src/locale/en-US.ts @@ -90,6 +90,11 @@ export function enUSLocale() { cancel: 'Cancel' }, + numberInput: { + placeholder: 'Please input number', + outOfRange: 'Out of range' + }, + pagination: { page: 'Page | Pages', perPage: '/ Page', diff --git a/common/config/src/locale/helper.ts b/common/config/src/locale/helper.ts index 13ccd3659..4b8a165d7 100644 --- a/common/config/src/locale/helper.ts +++ b/common/config/src/locale/helper.ts @@ -91,6 +91,11 @@ export interface LocaleConfig { cancel: string }, + numberInput: { + placeholder: string, + outOfRange: string + }, + pagination: { page: string, perPage: string, diff --git a/common/config/src/locale/ta-IN.ts b/common/config/src/locale/ta-IN.ts index 87a251423..a73e2fd8b 100644 --- a/common/config/src/locale/ta-IN.ts +++ b/common/config/src/locale/ta-IN.ts @@ -90,6 +90,11 @@ export function taINLocale() { cancel: 'நிராகரி' }, + numberInput: { + placeholder: 'தயவுசெய்து எண் உள்ளிடவும்', + outOfRange: 'வரம்புக்கு வெளியே' + }, + pagination: { page: 'பக்கம் | பக்கங்கள்', perPage: '/ பக்கம்', diff --git a/common/config/src/locale/zh-CN.ts b/common/config/src/locale/zh-CN.ts index eba65947c..d87260724 100644 --- a/common/config/src/locale/zh-CN.ts +++ b/common/config/src/locale/zh-CN.ts @@ -90,6 +90,11 @@ export function zhCNLocale() { cancel: '取消' }, + numberInput: { + placeholder: '请输入数字', + outOfRange: '超出范围' + }, + pagination: { page: '页', perPage: '条/页', diff --git a/components/number-input/number-input.vue b/components/number-input/number-input.vue index fd6ef2c2a..58b37933d 100644 --- a/components/number-input/number-input.vue +++ b/components/number-input/number-input.vue @@ -27,6 +27,7 @@ :readonly="isReadonly" :placeholder="props.placeholder ?? locale.placeholder" role="spinbutton" + :title="outOfRange ? locale.outOfRange : undefined" :aria-valuenow="preciseNumber" :aria-valuemin="props.min !== -Infinity ? props.min : undefined" :aria-valuemax="props.max !== Infinity ? props.max : undefined" @@ -107,6 +108,7 @@ type InputEventType = 'input' | 'change' const numberRE = /^-?[0-9]*\.?[0-9]*$/ const isEmpty = (value: unknown) => !value && value !== 0 +const isNullOrNaN = (value: unknown) => isNull(value) || Number.isNaN(value) export default defineComponent({ name: 'NumberInput', @@ -208,11 +210,18 @@ export default defineComponent({ let lastValue = props.value + const outOfRange = computed(() => { + return ( + !isNullOrNaN(currentValue.value) && + (toNumber(currentValue.value) > props.max || toNumber(currentValue.value) < props.min) + ) + }) const className = computed(() => { const [display, fade] = (props.controlType || 'right').split('-') return [ nh.b(), + nh.bs('vars'), nh.ns('input-vars'), { [nh.bm('inherit')]: props.inherit, @@ -222,7 +231,8 @@ export default defineComponent({ [nh.bm(props.size)]: props.size !== 'default', [nh.bm(props.state)]: props.state !== 'default', [nh.bm(`control-${display}`)]: display !== 'right', - [nh.bm('control-fade')]: fade + [nh.bm('control-fade')]: fade, + [nh.bm('out-of-range')]: outOfRange.value } ] }) @@ -460,12 +470,13 @@ export default defineComponent({ return { props, nh, - locale: useLocale('input', toRef(props, 'locale')), + locale: useLocale('numberInput', toRef(props, 'locale')), icons: useIcons(), idFor, focused, isHover, + outOfRange, className, hasPrefix, hasSuffix, diff --git a/components/number-input/tests/number-input.spec.tsx b/components/number-input/tests/number-input.spec.tsx index 9bc9cbfde..d428278ff 100644 --- a/components/number-input/tests/number-input.spec.tsx +++ b/components/number-input/tests/number-input.spec.tsx @@ -427,4 +427,25 @@ describe('NumberInput', () => { await nextTick() expect(onChange).toHaveBeenCalledWith(NUMBER) }) + + it('range', async () => { + const onChange = vi.fn() + const wrapper = mount(NumberInput, { + props: { min: 5, max: 10, onChange } + }) + const input = wrapper.find('input').element + + emitChange(input, 11) + await nextTick() + expect(onChange).toHaveBeenLastCalledWith(10) + + emitChange(input, 4) + await nextTick() + expect(onChange).toHaveBeenLastCalledWith(5) + + emitInput(input, 11) + vi.runAllTimers() + await nextTick() + expect(wrapper.find('.vxp-number-input').classes()).toContain('vxp-number-input--out-of-range') + }) }) diff --git a/style/input.scss b/style/input.scss index a81c2554d..b35ef89fe 100644 --- a/style/input.scss +++ b/style/input.scss @@ -158,6 +158,7 @@ $input: map.merge( border: 0; border-radius: get-css-var('input-radius'); outline: 0; + transition: get-css-var('transition-color'); &:disabled { cursor: not-allowed; diff --git a/style/number-input.scss b/style/number-input.scss index 7e7e6ea3f..c841e1ee4 100644 --- a/style/number-input.scss +++ b/style/number-input.scss @@ -4,7 +4,19 @@ @use './design' as *; @use './input.scss' as input; +$number-input: () !default; +$number-input: map.merge( + ( + control-color-out: get-css-var('color-error-base') + ), + $number-input +); + .#{$namespace}-number-input { + &-vars { + @include define-preset-values('number-input', $number-input); + } + @include basis; @include input.handler; @@ -14,6 +26,10 @@ } } + &--out-of-range &__control { + color: get-css-var('number-input-control-color-out'); + } + &__clear, &__loading { right: calc(get-css-var('input-h-padding') + 20px);