Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 23 additions & 44 deletions src/packages/input/input.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@tarojs/components'
import { MaskClose } from '@nutui/icons-react-taro'
import Taro, { ENV_TYPE, getEnv } from '@tarojs/taro'
import { BaseEventOrig } from '@tarojs/components/types/common'
import { formatNumber } from './utils'
import { useConfig, useRtl } from '@/packages/configprovider/index.taro'
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
Expand All @@ -39,7 +40,7 @@ export interface InputProps extends BasicComponent {
autoFocus: boolean
confirmType: InputConfirmType
plain: boolean
formatter?: (value: string) => void
formatter?: (value: string) => string
onChange?: (value: string) => void
onBlur?: (value: string) => void
onFocus?: (value: string, height?: number) => void
Expand Down Expand Up @@ -153,23 +154,14 @@ export const Input = forwardRef(
trigger: InputFormatTrigger = 'onChange'
) => {
let val = value
if (type === 'number') {
val = formatNumber(val, false, true)
}
if (type === 'digit') {
val = formatNumber(val, true, true)
}
if (formatter && trigger === formatTrigger) {
val = formatter(val)
}
if (type === 'number') val = formatNumber(val, false, true)
if (type === 'digit') val = formatNumber(val, true, true)
if (formatter && trigger === formatTrigger) val = formatter(val)

setValue(val)
const eventHandler = props[trigger]
if (
eventHandler &&
typeof eventHandler === 'function' &&
trigger !== 'onChange'
) {
eventHandler(val)
if (trigger !== 'onChange') {
const eventHandler = props[trigger]
eventHandler?.(val)
Comment thread
oasis-cloud marked this conversation as resolved.
}
forceUpdate()
}
Expand All @@ -185,31 +177,31 @@ export const Input = forwardRef(
setActive(true)
}

const handleInput = (value: string) => {
updateValue(value, 'onChange')
const handleInput = (event: BaseEventOrig) => {
updateValue((event.detail || event.currentTarget).value, 'onChange')
}

const handleBlur = (event: any) => {
const val = Taro.getEnv() === 'WEB' ? (event.target as any).value : value
updateValue(val, 'onBlur')
setTimeout(() => {
setActive(false)
}, 200)
setTimeout(() => setActive(false), 200)
}
const inputType = (type: any) => {
if (getEnv() === ENV_TYPE.WEB) {
if (type === 'digit') {
return 'text'
}
if (type === 'number') {
return 'tel'
}
if (type === 'digit') return 'text'
if (type === 'number') return 'tel'
} else if (type === 'password') {
return 'text'
}
return type
}

const getTextAlign = () => {
if (rtl) {
if (align === 'right') return 'left'
if (align === 'left') return 'right'
}
return align
}
return (
<View
className={`${inputClass()} ${className || ''}`}
Expand All @@ -223,18 +215,7 @@ export const Input = forwardRef(
name={name}
className="nut-input-native"
ref={inputRef}
style={{
// eslint-disable-next-line no-nested-ternary
textAlign: rtl
? // eslint-disable-next-line no-nested-ternary
align === 'right'
? // eslint-disable-next-line no-nested-ternary
'left'
: align === 'left'
? 'right'
: 'center'
: align,
}}
style={getTextAlign()}
type={inputType(type) as any}
password={type === 'password'}
maxlength={maxLength}
Expand All @@ -247,9 +228,7 @@ export const Input = forwardRef(
confirmType={confirmType}
onBlur={handleBlur}
onFocus={handleFocus}
onInput={(e: any) => {
handleInput((e.detail || e.currentTarget).value)
}}
onInput={handleInput}
/>
<View
style={{
Expand Down
168 changes: 68 additions & 100 deletions src/packages/input/input.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, {
useCallback,
useRef,
HTMLInputTypeAttribute,
forwardRef,
HTMLInputTypeAttribute,
MouseEvent,
useCallback,
useImperativeHandle,
useRef,
useState,
MouseEvent,
} from 'react'
import { MaskClose } from '@nutui/icons-react'
import { formatNumber } from './utils'
Expand Down Expand Up @@ -34,15 +34,15 @@ export interface InputProps extends BasicComponent {
autoFocus: boolean
confirmType: InputConfirmType
plain: boolean
formatter?: (value: string) => void
formatter?: (value: string) => string
onChange?: (value: string) => void
onBlur?: (value: string) => void
onFocus?: (value: string) => void
onClear?: (value: string) => void
onClick?: (value: MouseEvent<HTMLDivElement>) => void
onClick?: (event: MouseEvent<HTMLDivElement>) => void
}

const defaultProps = {
const defaultProps: InputProps = {
...ComponentDefaults,
type: 'text',
name: '',
Expand Down Expand Up @@ -71,6 +71,7 @@ export const Input = forwardRef(
) => {
const rtl = useRtl()
const { locale } = useConfig()

const {
type,
name,
Expand All @@ -97,129 +98,102 @@ export const Input = forwardRef(
onCompositionStart,
onCompositionEnd,
...rest
} = {
...defaultProps,
...props,
}
} = { ...defaultProps, ...props }

const [value, setValue] = usePropsValue<string>({
value: _value,
defaultValue,
finalValue: '',
onChange,
})

const inputRef = useRef<HTMLInputElement>(null)
const composingRef = useRef(false)
const [active, setActive] = useState(false)

useImperativeHandle(ref, () => {
return {
clear: () => {
setValue('')
},
focus: () => {
inputRef.current?.focus()
},
blur: () => {
inputRef.current?.blur()
},
get nativeElement() {
return inputRef.current
},
}
})
useImperativeHandle(ref, () => ({
clear: () => setValue(''),
focus: () => inputRef.current?.focus(),
blur: () => inputRef.current?.blur(),
get nativeElement() {
return inputRef.current
},
}))

const inputClass = useCallback(() => {
const getInputClass = useCallback(() => {
const classPrefix = 'nut-input'
return [
classPrefix,
disabled ? `${classPrefix}-disabled` : '',
`${disabled ? `${classPrefix}-disabled` : ''}`,
readOnly ? `${classPrefix}-readonly` : '',
plain ? `${classPrefix}-plain` : `${classPrefix}-container`,
`${plain ? `${classPrefix}-plain` : `${classPrefix}-container`}`,
]
.filter(Boolean)
.join(' ')
}, [disabled])
}, [disabled, readOnly, plain])

const updateValue = (
value: any,
trigger: InputFormatTrigger = 'onChange'
const handleValueUpdate = (
inputValue: string,
trigger: InputFormatTrigger
) => {
let val = value
let updatedValue = inputValue

if (type === 'number') {
val = formatNumber(val, false, true)
}
if (type === 'digit') {
val = formatNumber(val, true, true)
}
if (formatter && trigger === formatTrigger) {
val = formatter(val)
}
setValue(val)
const eventHandler = props[trigger]
if (
eventHandler &&
typeof eventHandler === 'function' &&
trigger !== 'onChange'
) {
eventHandler(val)
if (type === 'number')
updatedValue = formatNumber(updatedValue, false, true)
if (type === 'digit')
updatedValue = formatNumber(updatedValue, true, true)
if (formatter && trigger === formatTrigger)
updatedValue = formatter(updatedValue)

setValue(updatedValue)

if (trigger !== 'onChange') {
const eventHandler = props[trigger]
eventHandler?.(updatedValue)
}
}

const handleFocus = (event: Event) => {
const val: any = (event.target as any).value
onFocus && onFocus(val)
const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
onFocus?.(event.target.value)
setActive(true)
}

const handleInput = (value: string) => {
updateValue(value, 'onChange')
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
handleValueUpdate(event.target.value, 'onBlur')
setTimeout(() => setActive(false), 200)
}

const handleBlur = (event: Event) => {
const val: any = (event.target as any).value
updateValue(val, 'onBlur')
setTimeout(() => {
setActive(false)
}, 200)
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
handleValueUpdate(event.target.value, 'onChange')
}

const inputType = (type: string) => {
if (type === 'digit') {
return 'text'
}
if (type === 'number') {
return 'tel'
const getInputType = (inputType: InputType) => {
if (inputType === 'digit') return 'text'
if (inputType === 'number') return 'tel'
return inputType
}

const getTextAlign = () => {
if (rtl) {
if (align === 'right') return 'left'
if (align === 'left') return 'right'
}
return type
return align
}

return (
<div
className={`${inputClass()} ${className || ''}`}
className={`${getInputClass()} ${className || ''}`}
style={style}
onClick={(e) => {
onClick && onClick(e)
}}
onClick={onClick}
>
<input
{...rest}
ref={inputRef}
name={name}
className="nut-input-native"
ref={inputRef}
style={{
// eslint-disable-next-line no-nested-ternary
textAlign: rtl
? // eslint-disable-next-line no-nested-ternary
align === 'right'
? // eslint-disable-next-line no-nested-ternary
'left'
: align === 'left'
? 'right'
: 'center'
: align,
}}
type={inputType(type)}
style={{ textAlign: getTextAlign() }}
type={getInputType(type)}
maxLength={maxLength}
placeholder={
placeholder === undefined ? locale.placeholder : placeholder
Expand All @@ -229,15 +203,9 @@ export const Input = forwardRef(
value={value}
autoFocus={autoFocus}
enterKeyHint={confirmType}
onBlur={(e: any) => {
handleBlur(e)
}}
onFocus={(e: any) => {
handleFocus(e)
}}
onChange={(e: any) => {
handleInput(e.currentTarget.value)
}}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleInputChange}
onCompositionStart={(e) => {
composingRef.current = true
onCompositionStart?.(e)
Expand All @@ -247,19 +215,19 @@ export const Input = forwardRef(
onCompositionEnd?.(e)
}}
/>
{clearable && !readOnly && active && value.length > 0 ? (
{clearable && !readOnly && active && value.length > 0 && (
<span
style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}
onClick={() => {
if (!disabled) {
setValue('')
onClear && onClear('')
onClear?.('')
}
}}
>
{clearIcon || <MaskClose className="nut-input-clear" />}
</span>
) : null}
)}
</div>
)
}
Expand Down