mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-24 12:45:18 +08:00
refactor(input): ts
This commit is contained in:
parent
e6568da5e4
commit
e505f6e1b9
@ -1,4 +1,4 @@
|
|||||||
import { h, defineComponent, PropType } from 'vue'
|
import { h, defineComponent, PropType, renderSlot } from 'vue'
|
||||||
import { useStyle } from '../../../_mixins'
|
import { useStyle } from '../../../_mixins'
|
||||||
import { DismissCircleIcon } from '../../icons'
|
import { DismissCircleIcon } from '../../icons'
|
||||||
import NBaseIcon from '../../icon'
|
import NBaseIcon from '../../icon'
|
||||||
@ -43,11 +43,11 @@ export default defineComponent({
|
|||||||
onClick={this.onClear}
|
onClick={this.onClear}
|
||||||
onMousedown={this.handleMouseDown}
|
onMousedown={this.handleMouseDown}
|
||||||
>
|
>
|
||||||
<DismissCircleIcon />
|
{{ default: () => <DismissCircleIcon /> }}
|
||||||
</NBaseIcon>
|
</NBaseIcon>
|
||||||
) : (
|
) : (
|
||||||
<div key="icon" class="n-base-clear__placeholder">
|
<div key="icon" class="n-base-clear__placeholder">
|
||||||
<slot />
|
{renderSlot(this.$slots, 'default')}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ import createIconSwitchTransition from '../../../../_styles/transitions/icon-swi
|
|||||||
|
|
||||||
// vars:
|
// vars:
|
||||||
// --bezier
|
// --bezier
|
||||||
// --color
|
// --clear-color
|
||||||
// --size
|
// --clear-size
|
||||||
// --color-hover
|
// --clear-color-hover
|
||||||
// --color-pressed
|
// --clear-color-pressed
|
||||||
export default cB(
|
export default cB(
|
||||||
'base-clear',
|
'base-clear',
|
||||||
{
|
{
|
||||||
@ -22,15 +22,15 @@ export default cB(
|
|||||||
{
|
{
|
||||||
fontSize: 'var(--size)',
|
fontSize: 'var(--size)',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
color: 'var(--color)',
|
color: 'var(--clear-color)',
|
||||||
transition: 'color .3s var(--bezier)'
|
transition: 'color .3s var(--bezier)'
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
c('&:hover', {
|
c('&:hover', {
|
||||||
color: 'var(--color-hover)!important'
|
color: 'var(--clear-color-hover)!important'
|
||||||
}),
|
}),
|
||||||
c('&:active', {
|
c('&:active', {
|
||||||
color: 'var(--color-pressed)!important'
|
color: 'var(--clear-color-pressed)!important'
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
@ -14,7 +14,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
useStyle('BaseClose', style)
|
useStyle('BaseClose', style)
|
||||||
return (
|
return () => (
|
||||||
<NBaseIcon
|
<NBaseIcon
|
||||||
class={[
|
class={[
|
||||||
'n-base-close',
|
'n-base-close',
|
||||||
@ -23,7 +23,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
{{ default: () => <CloseIcon /> }}
|
||||||
</NBaseIcon>
|
</NBaseIcon>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { computed, inject, provide, onBeforeUnmount } from 'vue'
|
import { computed, inject, provide, onBeforeUnmount, ComputedRef } from 'vue'
|
||||||
|
|
||||||
|
type FormItemSize = 'small' | 'medium' | 'large'
|
||||||
|
type AllowedSize = 'tiny' | 'small' | 'medium' | 'large' | 'huge'
|
||||||
|
|
||||||
interface FormItemInjection {
|
interface FormItemInjection {
|
||||||
size: string | undefined
|
mergedSize: FormItemSize
|
||||||
mergedSize: string
|
|
||||||
restoreValidation: () => void
|
restoreValidation: () => void
|
||||||
handleContentBlur: () => void
|
handleContentBlur: () => void
|
||||||
handleContentFocus: () => void
|
handleContentFocus: () => void
|
||||||
@ -10,19 +12,27 @@ interface FormItemInjection {
|
|||||||
handleContentChange: () => void
|
handleContentChange: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UseFormItemOptions {
|
interface UseFormItemOptions<T> {
|
||||||
defaultSize?: string
|
defaultSize?: FormItemSize
|
||||||
mergedSize?: (formItem: FormItemInjection | null) => string
|
mergedSize?: (formItem: FormItemInjection | null) => T
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UseFormItemProps {
|
interface UseFormItemProps<T> {
|
||||||
size?: string
|
size?: T
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useFormItem (
|
interface UseFormItem<T> {
|
||||||
props: UseFormItemProps,
|
mergedSize: ComputedRef<T>
|
||||||
{ defaultSize = 'medium', mergedSize }: UseFormItemOptions = {}
|
nTriggerFormBlur: () => void
|
||||||
) {
|
nTriggerFormChange: () => void
|
||||||
|
nTriggerFormFocus: () => void
|
||||||
|
nTriggerFormInput: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useFormItem<T extends AllowedSize = FormItemSize> (
|
||||||
|
props: UseFormItemProps<T>,
|
||||||
|
{ defaultSize = 'medium', mergedSize }: UseFormItemOptions<T> = {}
|
||||||
|
): UseFormItem<T> {
|
||||||
const NFormItem = inject<FormItemInjection | null>('NFormItem', null)
|
const NFormItem = inject<FormItemInjection | null>('NFormItem', null)
|
||||||
provide('NFormItem', null)
|
provide('NFormItem', null)
|
||||||
const mergedSizeRef = computed(
|
const mergedSizeRef = computed(
|
||||||
@ -34,10 +44,10 @@ export default function useFormItem (
|
|||||||
if (NFormItem) {
|
if (NFormItem) {
|
||||||
const { mergedSize } = NFormItem
|
const { mergedSize } = NFormItem
|
||||||
if (mergedSize) {
|
if (mergedSize) {
|
||||||
return mergedSize
|
return (mergedSize as unknown) as T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return defaultSize
|
return (defaultSize as unknown) as T
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
@ -8,6 +8,7 @@ export {
|
|||||||
keysOf,
|
keysOf,
|
||||||
render
|
render
|
||||||
} from './vue'
|
} from './vue'
|
||||||
|
export type { MaybeArray } from './vue'
|
||||||
export { warn, warnOnce } from './naive'
|
export { warn, warnOnce } from './naive'
|
||||||
export { formatLength } from './css'
|
export { formatLength } from './css'
|
||||||
export { createKey } from './cssr'
|
export { createKey } from './cssr'
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
export function call<A extends any[]> (funcs: Function[] | Function, ...args: A): void {
|
export function call<A extends any[]> (
|
||||||
|
funcs: Function[] | Function,
|
||||||
|
...args: A
|
||||||
|
): void {
|
||||||
if (Array.isArray(funcs)) funcs.forEach((func) => call(func, ...args))
|
if (Array.isArray(funcs)) funcs.forEach((func) => call(func, ...args))
|
||||||
else return funcs(...args)
|
else return funcs(...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MaybeArray<T> = T | T[]
|
||||||
|
@ -6,3 +6,4 @@ export { flatten } from './flatten'
|
|||||||
export { call } from './call'
|
export { call } from './call'
|
||||||
export { keysOf } from './keysOf'
|
export { keysOf } from './keysOf'
|
||||||
export { render } from './render'
|
export { render } from './render'
|
||||||
|
export type { MaybeArray } from './call'
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
/* istanbul ignore file */
|
|
||||||
export { default as NInput } from './src/Input.vue'
|
|
||||||
export { default as NInputGroup } from './src/InputGroup.vue'
|
|
||||||
export { default as NInputGroupLabel } from './src/InputGroupLabel.vue'
|
|
4
src/input/index.ts
Normal file
4
src/input/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
export { default as NInput } from './src/Input'
|
||||||
|
export { default as NInputGroup } from './src/InputGroup'
|
||||||
|
export { default as NInputGroupLabel } from './src/InputGroupLabel'
|
929
src/input/src/Input.tsx
Normal file
929
src/input/src/Input.tsx
Normal file
@ -0,0 +1,929 @@
|
|||||||
|
import {
|
||||||
|
h,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
nextTick,
|
||||||
|
ref,
|
||||||
|
toRef,
|
||||||
|
watch,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
renderSlot,
|
||||||
|
PropType,
|
||||||
|
CSSProperties
|
||||||
|
} from 'vue'
|
||||||
|
import { useMergedState } from 'vooks'
|
||||||
|
import NIconConfigProvider from '../../icon/src/IconConfigProvider'
|
||||||
|
import { NBaseClear } from '../../_base'
|
||||||
|
import { useTheme, useLocale, useFormItem, useConfig } from '../../_mixins'
|
||||||
|
import type { ThemeProps } from '../../_mixins'
|
||||||
|
import { call, createKey } from '../../_utils'
|
||||||
|
import type { MaybeArray } from '../../_utils'
|
||||||
|
import { inputLight } from '../styles'
|
||||||
|
import type { InputTheme } from '../styles'
|
||||||
|
import style from './styles/input.cssr'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Input',
|
||||||
|
props: {
|
||||||
|
...(useTheme.props as ThemeProps<InputTheme>),
|
||||||
|
bordered: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'text'
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: [Array, String] as PropType<undefined | string | [string, string]>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
defaultValue: {
|
||||||
|
type: [String, Array] as PropType<null | string | [string, string]>,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Array] as PropType<
|
||||||
|
null | undefined | string | [string, string]
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String as PropType<'small' | 'medium' | 'large' | undefined>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: [Number, String] as PropType<number | string>,
|
||||||
|
default: 3
|
||||||
|
},
|
||||||
|
round: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
minlength: {
|
||||||
|
type: [String, Number] as PropType<number | string | undefined>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
maxlength: {
|
||||||
|
type: [String, Number] as PropType<number | string | undefined>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
clearable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
autosize: {
|
||||||
|
type: [Boolean, Object] as PropType<
|
||||||
|
false | { minRows?: number, maxRows?: number }
|
||||||
|
>,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showWordLimit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
pair: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: [String, Boolean],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
forceFocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
passivelyActivated: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
stateful: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
autofocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
onInput: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
| undefined
|
||||||
|
| MaybeArray<(value: string) => void>
|
||||||
|
| MaybeArray<(value: [string, string]) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onFocus: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onBlur: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onClick: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: MouseEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onChange: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
| undefined
|
||||||
|
| MaybeArray<(value: string) => void>
|
||||||
|
| MaybeArray<(value: [string, string]) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onClear: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: MouseEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line vue/prop-name-casing
|
||||||
|
'onUpdate:value': {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(value: string) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
/** private */
|
||||||
|
textDecoration: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
attrSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 20
|
||||||
|
},
|
||||||
|
onInputBlur: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onInputFocus: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onDeactivate: {
|
||||||
|
type: [Function, Array] as PropType<undefined | MaybeArray<() => void>>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onActivate: {
|
||||||
|
type: [Function, Array] as PropType<undefined | MaybeArray<() => void>>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onWrapperFocus: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
onWrapperBlur: {
|
||||||
|
type: [Function, Array] as PropType<
|
||||||
|
undefined | MaybeArray<(e: FocusEvent) => void>
|
||||||
|
>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
deactivateOnEnter: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup (props) {
|
||||||
|
const themeRef = useTheme('Input', 'Input', style, inputLight, props)
|
||||||
|
// dom refs
|
||||||
|
const wrapperRef = ref<HTMLElement | null>(null)
|
||||||
|
const textareaRef = ref<HTMLElement | null>(null)
|
||||||
|
const textareaMirrorRef = ref<HTMLElement | null>(null)
|
||||||
|
const inputRef = ref<HTMLElement | null>(null)
|
||||||
|
const input2Ref = ref<HTMLElement | null>(null)
|
||||||
|
// local
|
||||||
|
const { locale } = useLocale('Input')
|
||||||
|
// value
|
||||||
|
const uncontrolledValueRef = ref(props.defaultValue)
|
||||||
|
const controlledValueRef = toRef(props, 'value')
|
||||||
|
const mergedValueRef = useMergedState(
|
||||||
|
controlledValueRef,
|
||||||
|
uncontrolledValueRef
|
||||||
|
)
|
||||||
|
// form-item
|
||||||
|
const formItem = useFormItem(props)
|
||||||
|
const { mergedSize: mergedSizeRef } = formItem
|
||||||
|
// states
|
||||||
|
const focusedRef = ref(false)
|
||||||
|
const hoverRef = ref(false)
|
||||||
|
const isComposingRef = ref(false)
|
||||||
|
const activatedRef = ref(false)
|
||||||
|
// placeholder
|
||||||
|
const mergedPlaceholderRef = computed<[string, string] | [string]>(() => {
|
||||||
|
const { placeholder, pair } = props
|
||||||
|
if (pair) {
|
||||||
|
if (Array.isArray(placeholder)) {
|
||||||
|
return placeholder
|
||||||
|
} else if (placeholder === undefined) {
|
||||||
|
return ['', '']
|
||||||
|
}
|
||||||
|
return [placeholder, placeholder]
|
||||||
|
} else if (placeholder === undefined) {
|
||||||
|
return [locale.value.placeholder]
|
||||||
|
} else {
|
||||||
|
return [placeholder] as [string]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const showPlaceholder1Ref = computed(() => {
|
||||||
|
const { value: isComposing } = isComposingRef
|
||||||
|
const { value: mergedValue } = mergedValueRef
|
||||||
|
const { value: mergedPlaceholder } = mergedPlaceholderRef
|
||||||
|
return (
|
||||||
|
!isComposing &&
|
||||||
|
(!mergedValue || (Array.isArray(mergedValue) && !mergedValue[0])) &&
|
||||||
|
mergedPlaceholder[0]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
const showPlaceholder2Ref = computed(() => {
|
||||||
|
const { value: isComposing } = isComposingRef
|
||||||
|
const { value: mergedValue } = mergedValueRef
|
||||||
|
const { value: mergedPlaceholder } = mergedPlaceholderRef
|
||||||
|
return (
|
||||||
|
!isComposing &&
|
||||||
|
mergedPlaceholder[1] &&
|
||||||
|
(!mergedValue || (Array.isArray(mergedValue) && !mergedValue[1]))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
const showTextareaPlaceholderRef = computed(() => {
|
||||||
|
return (
|
||||||
|
props.type === 'textarea' &&
|
||||||
|
!isComposingRef.value &&
|
||||||
|
!mergedValueRef.value &&
|
||||||
|
mergedPlaceholderRef.value
|
||||||
|
)
|
||||||
|
})
|
||||||
|
// clear
|
||||||
|
const showClearButton = computed(() => {
|
||||||
|
if (
|
||||||
|
props.disabled ||
|
||||||
|
!props.clearable ||
|
||||||
|
(!mergedFocusRef.value && !hoverRef.value)
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const { value: mergedValue } = mergedValueRef
|
||||||
|
const { value: mergedFocus } = mergedFocusRef
|
||||||
|
if (props.pair) {
|
||||||
|
return (
|
||||||
|
!!(
|
||||||
|
Array.isArray(mergedValue) &&
|
||||||
|
(mergedValue[0] || mergedValue[1])
|
||||||
|
) &&
|
||||||
|
(hoverRef.value || mergedFocus)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return !!mergedValue && (hoverRef.value || mergedFocus)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// focus
|
||||||
|
const mergedFocusRef = computed(() => {
|
||||||
|
return props.forceFocus || focusedRef.value
|
||||||
|
})
|
||||||
|
// text-decoration
|
||||||
|
const textDecorationStyleRef = computed(() => {
|
||||||
|
const { textDecoration } = props
|
||||||
|
if (!textDecoration) return ['', '']
|
||||||
|
if (Array.isArray(textDecoration)) {
|
||||||
|
return textDecoration.map((v) => ({
|
||||||
|
textDecoration: v
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
textDecoration
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
// textarea autosize
|
||||||
|
const updateTextAreaStyle = (): void => {
|
||||||
|
if (props.type === 'textarea') {
|
||||||
|
const { autosize } = props
|
||||||
|
if (!autosize) return
|
||||||
|
if (!textareaRef.value) return
|
||||||
|
const {
|
||||||
|
paddingTop: stylePaddingTop,
|
||||||
|
paddingBottom: stylePaddingBottom,
|
||||||
|
lineHeight: styleLineHeight
|
||||||
|
} = window.getComputedStyle(textareaRef.value)
|
||||||
|
const paddingTop = Number(stylePaddingTop.slice(0, -2))
|
||||||
|
const paddingBottom = Number(stylePaddingBottom.slice(0, -2))
|
||||||
|
const lineHeight = Number(styleLineHeight.slice(0, -2))
|
||||||
|
if (!textareaMirrorRef.value) return
|
||||||
|
if (autosize.minRows) {
|
||||||
|
const minRows = Math.max(autosize.minRows, 1)
|
||||||
|
const styleMinHeight = `${
|
||||||
|
paddingTop + paddingBottom + lineHeight * minRows
|
||||||
|
}px`
|
||||||
|
textareaMirrorRef.value.style.minHeight = styleMinHeight
|
||||||
|
}
|
||||||
|
if (autosize.maxRows) {
|
||||||
|
const styleMaxHeight = `${
|
||||||
|
paddingTop + paddingBottom + lineHeight * autosize.maxRows
|
||||||
|
}px`
|
||||||
|
textareaMirrorRef.value.style.maxHeight = styleMaxHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch([mergedValueRef, mergedSizeRef], () => {
|
||||||
|
void nextTick(updateTextAreaStyle)
|
||||||
|
})
|
||||||
|
onMounted(updateTextAreaStyle)
|
||||||
|
// other methods
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const vm = getCurrentInstance()!.proxy!
|
||||||
|
function doInput (value: [string, string]): void
|
||||||
|
function doInput (value: string): void
|
||||||
|
function doInput (value: string | [string, string]): void {
|
||||||
|
const { 'onUpdate:value': onUpdateValue, onInput } = props
|
||||||
|
const { nTriggerFormInput } = formItem
|
||||||
|
if (onUpdateValue) call(onUpdateValue, value)
|
||||||
|
if (onInput) call(onInput, value)
|
||||||
|
uncontrolledValueRef.value = value
|
||||||
|
nTriggerFormInput()
|
||||||
|
}
|
||||||
|
function doChange (value: [string, string]): void
|
||||||
|
function doChange (value: string): void
|
||||||
|
function doChange (value: string | [string, string]): void {
|
||||||
|
const { onChange } = props
|
||||||
|
const { nTriggerFormChange } = formItem
|
||||||
|
if (onChange) call(onChange, value)
|
||||||
|
uncontrolledValueRef.value = value
|
||||||
|
nTriggerFormChange()
|
||||||
|
}
|
||||||
|
function doBlur (e: FocusEvent): void {
|
||||||
|
const { onBlur } = props
|
||||||
|
const { nTriggerFormBlur } = formItem
|
||||||
|
if (onBlur) call(onBlur, e)
|
||||||
|
nTriggerFormBlur()
|
||||||
|
}
|
||||||
|
function doFocus (e: FocusEvent): void {
|
||||||
|
const { onFocus } = props
|
||||||
|
const { nTriggerFormFocus } = formItem
|
||||||
|
if (onFocus) call(onFocus, e)
|
||||||
|
nTriggerFormFocus()
|
||||||
|
}
|
||||||
|
function doClear (e: MouseEvent): void {
|
||||||
|
const { onClear } = props
|
||||||
|
if (onClear) call(onClear, e)
|
||||||
|
}
|
||||||
|
function doInputBlur (e: FocusEvent): void {
|
||||||
|
const { onInputBlur } = props
|
||||||
|
if (onInputBlur) call(onInputBlur, e)
|
||||||
|
}
|
||||||
|
function doInputFocus (e: FocusEvent): void {
|
||||||
|
const { onInputFocus } = props
|
||||||
|
if (onInputFocus) call(onInputFocus, e)
|
||||||
|
}
|
||||||
|
function doDeactivate (): void {
|
||||||
|
const { onDeactivate } = props
|
||||||
|
if (onDeactivate) call(onDeactivate)
|
||||||
|
}
|
||||||
|
function doActivate (): void {
|
||||||
|
const { onActivate } = props
|
||||||
|
if (onActivate) call(onActivate)
|
||||||
|
}
|
||||||
|
function doClick (e: MouseEvent): void {
|
||||||
|
const { onClick } = props
|
||||||
|
if (onClick) call(onClick, e)
|
||||||
|
}
|
||||||
|
function doWrapperFocus (e: FocusEvent): void {
|
||||||
|
const { onWrapperFocus } = props
|
||||||
|
if (onWrapperFocus) call(onWrapperFocus, e)
|
||||||
|
}
|
||||||
|
function doWrapperBlur (e: FocusEvent): void {
|
||||||
|
const { onWrapperBlur } = props
|
||||||
|
if (onWrapperBlur) call(onWrapperBlur, e)
|
||||||
|
}
|
||||||
|
// methods
|
||||||
|
function handleCompositionStart (): void {
|
||||||
|
isComposingRef.value = true
|
||||||
|
}
|
||||||
|
function handleCompositionEnd (e: CompositionEvent): void {
|
||||||
|
isComposingRef.value = false
|
||||||
|
if (e.target === input2Ref.value) {
|
||||||
|
handleInput(e, 1)
|
||||||
|
} else {
|
||||||
|
handleInput(e, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleInput (
|
||||||
|
e: InputEvent | CompositionEvent | Event,
|
||||||
|
index: 0 | 1 = 0,
|
||||||
|
event = 'input'
|
||||||
|
): void {
|
||||||
|
if (isComposingRef.value) return
|
||||||
|
const changedValue = (e.target as HTMLInputElement).value
|
||||||
|
if (!props.pair) {
|
||||||
|
event === 'input' ? doInput(changedValue) : doChange(changedValue)
|
||||||
|
} else {
|
||||||
|
let { value } = mergedValueRef
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
value = ['', '']
|
||||||
|
} else {
|
||||||
|
value = [...value]
|
||||||
|
}
|
||||||
|
value[index] = changedValue
|
||||||
|
event === 'input' ? doInput(value) : doChange(value)
|
||||||
|
}
|
||||||
|
// force update to sync input's view with value
|
||||||
|
// if not set, after input, input value won't sync with dom input value
|
||||||
|
vm.$forceUpdate()
|
||||||
|
}
|
||||||
|
function handleInputBlur (e: FocusEvent): void {
|
||||||
|
doInputBlur(e)
|
||||||
|
if (e.relatedTarget === wrapperRef.value) {
|
||||||
|
doDeactivate()
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
e.relatedTarget !== null &&
|
||||||
|
(e.relatedTarget === inputRef.value ||
|
||||||
|
e.relatedTarget === input2Ref.value ||
|
||||||
|
e.relatedTarget === textareaRef.value)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
activatedRef.value = false
|
||||||
|
}
|
||||||
|
dealWithEvent(e, 'blur')
|
||||||
|
}
|
||||||
|
function handleInputFocus (e: FocusEvent): void {
|
||||||
|
doInputFocus(e)
|
||||||
|
focusedRef.value = true
|
||||||
|
activatedRef.value = true
|
||||||
|
doActivate()
|
||||||
|
dealWithEvent(e, 'focus')
|
||||||
|
}
|
||||||
|
function handleWrapperBlur (e: FocusEvent): void {
|
||||||
|
if (props.passivelyActivated) {
|
||||||
|
doWrapperBlur(e)
|
||||||
|
dealWithEvent(e, 'blur')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleWrapperFocus (e: FocusEvent): void {
|
||||||
|
if (props.passivelyActivated) {
|
||||||
|
focusedRef.value = true
|
||||||
|
doWrapperFocus(e)
|
||||||
|
dealWithEvent(e, 'focus')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function dealWithEvent (e: FocusEvent, type: 'focus' | 'blur'): void {
|
||||||
|
if (
|
||||||
|
e.relatedTarget !== null &&
|
||||||
|
(e.relatedTarget === inputRef.value ||
|
||||||
|
e.relatedTarget === input2Ref.value ||
|
||||||
|
e.relatedTarget === textareaRef.value ||
|
||||||
|
e.relatedTarget === wrapperRef.value)
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* activeElement transfer inside the input, do nothing
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
if (type === 'focus') {
|
||||||
|
doFocus(e)
|
||||||
|
focusedRef.value = true
|
||||||
|
} else if (type === 'blur') {
|
||||||
|
doBlur(e)
|
||||||
|
focusedRef.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleChange (e: Event, index?: 0 | 1): void {
|
||||||
|
handleInput(e, index, 'change')
|
||||||
|
}
|
||||||
|
function handleClick (e: MouseEvent): void {
|
||||||
|
doClick(e)
|
||||||
|
}
|
||||||
|
function handleClear (e: MouseEvent): void {
|
||||||
|
doClear(e)
|
||||||
|
if (props.pair) {
|
||||||
|
doInput(['', ''])
|
||||||
|
} else {
|
||||||
|
doInput('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleMouseEnter (): void {
|
||||||
|
hoverRef.value = true
|
||||||
|
}
|
||||||
|
function handleMouseLeave (): void {
|
||||||
|
hoverRef.value = false
|
||||||
|
}
|
||||||
|
function handleWrapperKeyDown (e: KeyboardEvent): void {
|
||||||
|
switch (e.code) {
|
||||||
|
case 'ESC':
|
||||||
|
handleWrapperKeyDownEsc()
|
||||||
|
break
|
||||||
|
case 'ENTER':
|
||||||
|
handleWrapperKeyDownEnter(e)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleWrapperKeyDownEnter (e: KeyboardEvent): void {
|
||||||
|
if (props.passivelyActivated) {
|
||||||
|
const { value: focused } = activatedRef
|
||||||
|
if (focused) {
|
||||||
|
if (props.deactivateOnEnter) {
|
||||||
|
handleWrapperKeyDownEsc()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
if (props.type === 'textarea') {
|
||||||
|
textareaRef.value?.focus()
|
||||||
|
} else {
|
||||||
|
inputRef.value?.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleWrapperKeyDownEsc (): void {
|
||||||
|
if (props.passivelyActivated) {
|
||||||
|
activatedRef.value = false
|
||||||
|
void nextTick(() => {
|
||||||
|
wrapperRef.value?.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function focus (): void {
|
||||||
|
if (props.disabled) return
|
||||||
|
if (props.passivelyActivated) {
|
||||||
|
wrapperRef.value?.focus()
|
||||||
|
} else {
|
||||||
|
textareaRef.value?.focus()
|
||||||
|
inputRef.value?.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function blur (): void {
|
||||||
|
if (wrapperRef.value?.contains(document.activeElement)) {
|
||||||
|
;(document.activeElement as HTMLElement).blur()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function activate (): void {
|
||||||
|
if (props.disabled) return
|
||||||
|
if (textareaRef.value) textareaRef.value.focus()
|
||||||
|
else if (inputRef.value) inputRef.value.focus()
|
||||||
|
}
|
||||||
|
function deactivate (): void {
|
||||||
|
const { value: wrapperEl } = wrapperRef
|
||||||
|
if (
|
||||||
|
wrapperEl?.contains(document.activeElement) &&
|
||||||
|
wrapperEl !== document.activeElement
|
||||||
|
) {
|
||||||
|
handleWrapperKeyDownEsc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
// DOM ref
|
||||||
|
wrapperRef,
|
||||||
|
inputRef,
|
||||||
|
input2Ref,
|
||||||
|
textareaRef,
|
||||||
|
textareaMirrorRef,
|
||||||
|
// value
|
||||||
|
uncontrolledValue: uncontrolledValueRef,
|
||||||
|
mergedValue: mergedValueRef,
|
||||||
|
mergedPlaceholder: mergedPlaceholderRef,
|
||||||
|
showPlaceholder1: showPlaceholder1Ref,
|
||||||
|
showPlaceholder2: showPlaceholder2Ref,
|
||||||
|
showTextareaPlaceholder: showTextareaPlaceholderRef,
|
||||||
|
mergedFocus: mergedFocusRef,
|
||||||
|
isComposing: isComposingRef,
|
||||||
|
activated: activatedRef,
|
||||||
|
showClearButton,
|
||||||
|
mergedSize: mergedSizeRef,
|
||||||
|
textDecorationStyle: textDecorationStyleRef,
|
||||||
|
// methods
|
||||||
|
focus,
|
||||||
|
blur,
|
||||||
|
deactivate,
|
||||||
|
activate,
|
||||||
|
handleCompositionStart,
|
||||||
|
handleCompositionEnd,
|
||||||
|
handleInput,
|
||||||
|
handleInputBlur,
|
||||||
|
handleInputFocus,
|
||||||
|
handleWrapperBlur,
|
||||||
|
handleWrapperFocus,
|
||||||
|
handleMouseEnter,
|
||||||
|
handleMouseLeave,
|
||||||
|
handleChange,
|
||||||
|
handleClick,
|
||||||
|
handleClear,
|
||||||
|
handleWrapperKeyDown,
|
||||||
|
...useConfig(props),
|
||||||
|
mergedTheme: themeRef,
|
||||||
|
cssVars: computed(() => {
|
||||||
|
const { value: size } = mergedSizeRef
|
||||||
|
const {
|
||||||
|
common: { cubicBezierEaseInOut },
|
||||||
|
self: {
|
||||||
|
color,
|
||||||
|
borderRadius,
|
||||||
|
paddingLeft,
|
||||||
|
paddingRight,
|
||||||
|
textColor,
|
||||||
|
caretColor,
|
||||||
|
textDecorationColor,
|
||||||
|
border,
|
||||||
|
borderDisabled,
|
||||||
|
borderHover,
|
||||||
|
borderFocus,
|
||||||
|
placeholderColor,
|
||||||
|
placeholderColorDisabled,
|
||||||
|
lineHeightTextarea,
|
||||||
|
colorDisabled,
|
||||||
|
colorFocus,
|
||||||
|
textColorDisabled,
|
||||||
|
boxShadowFocus,
|
||||||
|
iconSize,
|
||||||
|
colorFocusWarning,
|
||||||
|
boxShadowFocusWarning,
|
||||||
|
borderWarning,
|
||||||
|
borderFocusWarning,
|
||||||
|
borderHoverWarning,
|
||||||
|
colorFocusError,
|
||||||
|
boxShadowFocusError,
|
||||||
|
borderError,
|
||||||
|
borderFocusError,
|
||||||
|
borderHoverError,
|
||||||
|
clearSize,
|
||||||
|
clearColor,
|
||||||
|
clearColorHover,
|
||||||
|
clearColorPressed,
|
||||||
|
[createKey('fontSize', size)]: fontSize,
|
||||||
|
[createKey('height', size)]: height
|
||||||
|
}
|
||||||
|
} = themeRef.value
|
||||||
|
return {
|
||||||
|
'--bezier': cubicBezierEaseInOut,
|
||||||
|
'--color': color,
|
||||||
|
'--font-size': fontSize,
|
||||||
|
'--border-radius': borderRadius,
|
||||||
|
'--height': height,
|
||||||
|
'--padding-left': paddingLeft,
|
||||||
|
'--padding-right': paddingRight,
|
||||||
|
'--text-color': textColor,
|
||||||
|
'--caret-color': caretColor,
|
||||||
|
'--text-decoration-color': textDecorationColor,
|
||||||
|
'--border': border,
|
||||||
|
'--border-disabled': borderDisabled,
|
||||||
|
'--border-hover': borderHover,
|
||||||
|
'--border-focus': borderFocus,
|
||||||
|
'--placeholder-color': placeholderColor,
|
||||||
|
'--placeholder-color-disabled': placeholderColorDisabled,
|
||||||
|
'--icon-size': iconSize,
|
||||||
|
'--line-height-textarea': lineHeightTextarea,
|
||||||
|
'--color-disabled': colorDisabled,
|
||||||
|
'--color-focus': colorFocus,
|
||||||
|
'--text-color-disabled': textColorDisabled,
|
||||||
|
'--box-shadow-focus': boxShadowFocus,
|
||||||
|
// form warning
|
||||||
|
'--color-focus-warning': colorFocusWarning,
|
||||||
|
'--box-shadow-focus-warning': boxShadowFocusWarning,
|
||||||
|
'--border-warning': borderWarning,
|
||||||
|
'--border-focus-warning': borderFocusWarning,
|
||||||
|
'--border-hover-warning': borderHoverWarning,
|
||||||
|
// form error
|
||||||
|
'--color-focus-error': colorFocusError,
|
||||||
|
'--box-shadow-focus-error': boxShadowFocusError,
|
||||||
|
'--border-error': borderError,
|
||||||
|
'--border-focus-error': borderFocusError,
|
||||||
|
'--border-hover-error': borderHoverError,
|
||||||
|
// clear-button
|
||||||
|
'--clear-color': clearColor,
|
||||||
|
'--clear-size': clearSize,
|
||||||
|
'--clear-color-hover': clearColorHover,
|
||||||
|
'--clear-color-pressed': clearColorPressed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref="wrapperRef"
|
||||||
|
class={[
|
||||||
|
'n-input',
|
||||||
|
{
|
||||||
|
'n-input--disabled': this.disabled,
|
||||||
|
'n-input--textarea': this.type === 'textarea',
|
||||||
|
'n-input--round': this.round && !(this.type === 'textarea'),
|
||||||
|
'n-input--pair': this.pair,
|
||||||
|
'n-input--focus': this.mergedFocus,
|
||||||
|
'n-input--stateful': this.stateful
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
style={this.cssVars as CSSProperties}
|
||||||
|
tabindex={
|
||||||
|
!this.disabled && this.passivelyActivated && !this.activated
|
||||||
|
? 0
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onFocus={this.handleWrapperFocus}
|
||||||
|
onBlur={this.handleWrapperBlur}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
onMouseenter={this.handleMouseEnter}
|
||||||
|
onMouseleave={this.handleMouseLeave}
|
||||||
|
onCompositionstart={this.handleCompositionStart}
|
||||||
|
onCompositionend={this.handleCompositionEnd}
|
||||||
|
onKeydown={this.handleWrapperKeyDown}
|
||||||
|
>
|
||||||
|
{/* textarea mirror */}
|
||||||
|
{this.type === 'textarea' && this.autosize ? (
|
||||||
|
<pre ref="textareaMirrorRef" class="n-input__textarea-mirror">
|
||||||
|
{this.mergedValue}
|
||||||
|
<br />
|
||||||
|
</pre>
|
||||||
|
) : null}
|
||||||
|
{/* textarea & basic input */}
|
||||||
|
{this.type === 'textarea' ? (
|
||||||
|
<textarea
|
||||||
|
ref="textareaRef"
|
||||||
|
class={[
|
||||||
|
'n-input__textarea',
|
||||||
|
{
|
||||||
|
'n-input__textarea--autosize': this.autosize
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
autofocus={this.autofocus}
|
||||||
|
rows={Number(this.rows)}
|
||||||
|
placeholder={this.placeholder as string | undefined}
|
||||||
|
value={this.mergedValue as string | undefined}
|
||||||
|
disabled={this.disabled}
|
||||||
|
maxlength={this.maxlength as any}
|
||||||
|
minlength={this.minlength as any}
|
||||||
|
readonly={this.readonly as any}
|
||||||
|
tabindex={
|
||||||
|
this.passivelyActivated && !this.activated ? -1 : undefined
|
||||||
|
}
|
||||||
|
style={this.textDecorationStyle[0] as any}
|
||||||
|
onBlur={this.handleInputBlur}
|
||||||
|
onFocus={this.handleInputFocus}
|
||||||
|
onInput={this.handleInput}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div class="n-input-wrapper">
|
||||||
|
{this.$slots.affix || this.$slots.prefix ? (
|
||||||
|
<NIconConfigProvider
|
||||||
|
class="n-input__prefix"
|
||||||
|
depth={this.disabled ? 5 : 4}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () =>
|
||||||
|
renderSlot(this.$slots, 'affix', undefined, () => {
|
||||||
|
return [renderSlot(this.$slots, 'prefix')]
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</NIconConfigProvider>
|
||||||
|
) : null}
|
||||||
|
<div class="n-input__input">
|
||||||
|
<input
|
||||||
|
ref="inputRef"
|
||||||
|
type={this.type}
|
||||||
|
class="n-input__input-el"
|
||||||
|
tabindex={
|
||||||
|
this.passivelyActivated && !this.activated ? -1 : undefined
|
||||||
|
}
|
||||||
|
placeholder={this.mergedPlaceholder[0]}
|
||||||
|
disabled={this.disabled}
|
||||||
|
maxlength={this.maxlength as any}
|
||||||
|
minlength={this.minlength as any}
|
||||||
|
value={
|
||||||
|
Array.isArray(this.mergedValue)
|
||||||
|
? this.mergedValue[0]
|
||||||
|
: (this.mergedValue as any)
|
||||||
|
}
|
||||||
|
readonly={this.readonly as any}
|
||||||
|
autofocus={this.autofocus}
|
||||||
|
size={this.attrSize}
|
||||||
|
style={this.textDecorationStyle[0] as any}
|
||||||
|
onBlur={this.handleInputBlur}
|
||||||
|
onFocus={this.handleInputFocus}
|
||||||
|
onInput={(e) => this.handleInput(e, 0)}
|
||||||
|
onChange={(e) => this.handleChange(e, 0)}
|
||||||
|
/>
|
||||||
|
{this.showPlaceholder1 ? (
|
||||||
|
<div class="n-input__placeholder">
|
||||||
|
<span>{this.mergedPlaceholder[0]}</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
{!this.pair ? (
|
||||||
|
<NIconConfigProvider
|
||||||
|
class="n-input__suffix"
|
||||||
|
depth={this.disabled ? 5 : 4}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => [
|
||||||
|
renderSlot(this.$slots, 'suffix'),
|
||||||
|
this.clearable || this.$slots.clear ? (
|
||||||
|
<NBaseClear
|
||||||
|
show={this.showClearButton}
|
||||||
|
onClear={this.handleClear}
|
||||||
|
>
|
||||||
|
{{ default: () => renderSlot(this.$slots, 'clear') }}
|
||||||
|
</NBaseClear>
|
||||||
|
) : null
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
</NIconConfigProvider>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{/* pair input */}
|
||||||
|
{this.pair ? (
|
||||||
|
<span class="n-input__separator">
|
||||||
|
{renderSlot(this.$slots, 'separator', undefined, () => [
|
||||||
|
this.separator
|
||||||
|
])}
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
{this.pair ? (
|
||||||
|
<div v-if="pair" class="n-input-wrapper">
|
||||||
|
<div class="n-input__input">
|
||||||
|
<input
|
||||||
|
ref="input2Ref"
|
||||||
|
type={this.type}
|
||||||
|
class="n-input__input-el"
|
||||||
|
tabindex={
|
||||||
|
this.passivelyActivated && !this.activated ? -1 : undefined
|
||||||
|
}
|
||||||
|
placeholder={this.mergedPlaceholder[1]}
|
||||||
|
disabled={this.disabled}
|
||||||
|
maxlength={this.maxlength as any}
|
||||||
|
minlength={this.minlength as any}
|
||||||
|
value={
|
||||||
|
Array.isArray(this.mergedValue)
|
||||||
|
? this.mergedValue[1]
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
readonly={this.readonly as any}
|
||||||
|
style={this.textDecorationStyle[1] as any}
|
||||||
|
onBlur={this.handleInputBlur}
|
||||||
|
onFocus={this.handleInputFocus}
|
||||||
|
onInput={(e) => this.handleInput(e, 1)}
|
||||||
|
onChange={(e) => this.handleChange(e, 1)}
|
||||||
|
/>
|
||||||
|
{this.showPlaceholder2 ? (
|
||||||
|
<div class="n-input__placeholder">
|
||||||
|
<span>{this.mergedPlaceholder[1]}</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<NIconConfigProvider
|
||||||
|
class="n-input__suffix"
|
||||||
|
depth={this.disabled ? 5 : 4}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => {
|
||||||
|
return [
|
||||||
|
renderSlot(this.$slots, 'suffix'),
|
||||||
|
this.clearable || this.$slots.clear ? (
|
||||||
|
<NBaseClear
|
||||||
|
show={this.showClearButton}
|
||||||
|
onClear={this.handleClear}
|
||||||
|
>
|
||||||
|
{{ default: () => renderSlot(this.$slots, 'cleaar') }}
|
||||||
|
</NBaseClear>
|
||||||
|
) : null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</NIconConfigProvider>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{/* textarea placeholder */}
|
||||||
|
{this.showTextareaPlaceholder ? (
|
||||||
|
<div class="n-input__placeholder">{this.placeholder}</div>
|
||||||
|
) : null}
|
||||||
|
{/* border */}
|
||||||
|
{this.mergedBordered ? <div class="n-input__border" /> : null}
|
||||||
|
{this.mergedBordered ? <div class="n-input__state-border" /> : null}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
@ -1,878 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
ref="wrapperRef"
|
|
||||||
class="n-input"
|
|
||||||
:class="{
|
|
||||||
'n-input--disabled': disabled,
|
|
||||||
'n-input--textarea': type === 'textarea',
|
|
||||||
'n-input--round': round && !(type === 'textarea'),
|
|
||||||
'n-input--pair': pair,
|
|
||||||
'n-input--focus': mergedFocus,
|
|
||||||
'n-input--stateful': stateful
|
|
||||||
}"
|
|
||||||
:style="cssVars"
|
|
||||||
:tabindex="!disabled && passivelyActivated && !activated ? 0 : false"
|
|
||||||
@focus="handleWrapperFocus"
|
|
||||||
@blur="handleWrapperBlur"
|
|
||||||
@keydown.enter="handleWrapperKeyDownEnter"
|
|
||||||
@keydown.esc="handleWrapperKeyDownEsc"
|
|
||||||
@click="handleClick"
|
|
||||||
@mouseenter="handleMouseEnter"
|
|
||||||
@mouseleave="handleMouseLeave"
|
|
||||||
@compositionstart="handleCompositionStart"
|
|
||||||
@compositionend="handleCompositionEnd"
|
|
||||||
>
|
|
||||||
<pre
|
|
||||||
v-if="type === 'textarea' && autosize"
|
|
||||||
ref="textareaMirrorRef"
|
|
||||||
class="n-input__textarea-mirror">{{ mergedValue }}<br></pre>
|
|
||||||
<textarea
|
|
||||||
v-if="type === 'textarea'"
|
|
||||||
ref="textareaRef"
|
|
||||||
class="n-input__textarea"
|
|
||||||
:class="{
|
|
||||||
'n-input__textarea--autosize': autosize
|
|
||||||
}"
|
|
||||||
:autofocus="autofocus"
|
|
||||||
:rows="rows"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
:value="mergedValue"
|
|
||||||
:disabled="disabled"
|
|
||||||
:maxlength="maxlength"
|
|
||||||
:minlength="minlength"
|
|
||||||
:readonly="readonly"
|
|
||||||
:tabindex="passivelyActivated && !activated ? -1 : false"
|
|
||||||
:style="textDecorationStyle[0]"
|
|
||||||
@blur="handleInputBlur"
|
|
||||||
@focus="handleInputFocus"
|
|
||||||
@input="handleInput"
|
|
||||||
@change="handleChange"
|
|
||||||
@keyup="handleKeyUp"
|
|
||||||
/>
|
|
||||||
<div v-else class="n-input-wrapper">
|
|
||||||
<n-icon-config-provider
|
|
||||||
v-if="$slots.affix || $slots.prefix"
|
|
||||||
class="n-input__prefix"
|
|
||||||
:depth="disabled ? 5 : 4"
|
|
||||||
>
|
|
||||||
<slot name="affix">
|
|
||||||
<slot name="prefix" />
|
|
||||||
</slot>
|
|
||||||
</n-icon-config-provider>
|
|
||||||
<div class="n-input__input">
|
|
||||||
<input
|
|
||||||
ref="inputRef"
|
|
||||||
:type="type"
|
|
||||||
class="n-input__input-el"
|
|
||||||
:tabindex="passivelyActivated && !activated ? -1 : false"
|
|
||||||
:placeholder="mergedPlaceholder[0]"
|
|
||||||
:disabled="disabled"
|
|
||||||
:maxlength="maxlength"
|
|
||||||
:minlength="minlength"
|
|
||||||
:value="pair ? mergedValue && mergedValue[0] : mergedValue"
|
|
||||||
:readonly="readonly"
|
|
||||||
:autofocus="autofocus"
|
|
||||||
:size="attrSize"
|
|
||||||
:style="textDecorationStyle[0]"
|
|
||||||
@blur="handleInputBlur"
|
|
||||||
@focus="handleInputFocus"
|
|
||||||
@input="handleInput($event, 0)"
|
|
||||||
@change="handleChange($event, 0)"
|
|
||||||
@keyup="handleKeyUp"
|
|
||||||
/>
|
|
||||||
<div v-if="showPlaceholder1" class="n-input__placeholder">
|
|
||||||
<span>{{ mergedPlaceholder[0] }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<n-icon-config-provider
|
|
||||||
v-if="!pair"
|
|
||||||
class="n-input__suffix"
|
|
||||||
:depth="disabled ? 5 : 4"
|
|
||||||
>
|
|
||||||
<slot name="suffix" />
|
|
||||||
<n-base-clear
|
|
||||||
v-if="clearable || $slots.clear"
|
|
||||||
:unstable-theme="mergedTheme.peers.BaseClear"
|
|
||||||
:unstable-theme-overrides="mergedTheme.overrides.BaseClear"
|
|
||||||
:show="showClearButton"
|
|
||||||
@clear="handleClear"
|
|
||||||
>
|
|
||||||
<slot name="clear" />
|
|
||||||
</n-base-clear>
|
|
||||||
</n-icon-config-provider>
|
|
||||||
</div>
|
|
||||||
<span v-if="pair" class="n-input__separator">
|
|
||||||
<slot name="separator">
|
|
||||||
{{ separator }}
|
|
||||||
</slot>
|
|
||||||
</span>
|
|
||||||
<div v-if="pair" class="n-input-wrapper">
|
|
||||||
<div class="n-input__input">
|
|
||||||
<input
|
|
||||||
ref="input2Ref"
|
|
||||||
:type="type"
|
|
||||||
class="n-input__input-el"
|
|
||||||
:tabindex="passivelyActivated && !activated ? -1 : false"
|
|
||||||
:placeholder="mergedPlaceholder[1]"
|
|
||||||
:disabled="disabled"
|
|
||||||
:maxlength="maxlength"
|
|
||||||
:minlength="minlength"
|
|
||||||
:value="mergedValue && mergedValue[1]"
|
|
||||||
:readonly="readonly"
|
|
||||||
:style="textDecorationStyle[1]"
|
|
||||||
@blur="handleInputBlur"
|
|
||||||
@focus="handleInputFocus"
|
|
||||||
@input="handleInput($event, 1)"
|
|
||||||
@change="handleChange($event, 1)"
|
|
||||||
@keyup="handleKeyUp"
|
|
||||||
/>
|
|
||||||
<div v-if="showPlaceholder2" class="n-input__placeholder">
|
|
||||||
<span>{{ mergedPlaceholder[1] }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<n-icon-config-provider class="n-input__suffix" :depth="disabled ? 5 : 4">
|
|
||||||
<slot name="suffix" />
|
|
||||||
<n-base-clear
|
|
||||||
v-if="clearable || $slots.clear"
|
|
||||||
:unstable-theme="mergedTheme.peers.BaseClear"
|
|
||||||
:unstable-theme-overrides="mergedTheme.overrides.BaseClear"
|
|
||||||
:show="showClearButton"
|
|
||||||
@clear="handleClear"
|
|
||||||
>
|
|
||||||
<slot name="clear" />
|
|
||||||
</n-base-clear>
|
|
||||||
</n-icon-config-provider>
|
|
||||||
</div>
|
|
||||||
<div v-if="showTextareaPlaceholder" class="n-input__placeholder">
|
|
||||||
{{ placeholder }}
|
|
||||||
</div>
|
|
||||||
<div v-if="mergedBordered" class="n-input__border" />
|
|
||||||
<div v-if="mergedBordered" class="n-input__state-border" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
computed,
|
|
||||||
defineComponent,
|
|
||||||
nextTick,
|
|
||||||
ref,
|
|
||||||
toRef,
|
|
||||||
watch,
|
|
||||||
onMounted,
|
|
||||||
getCurrentInstance
|
|
||||||
} from 'vue'
|
|
||||||
import { useMergedState } from 'vooks'
|
|
||||||
import NIconConfigProvider from '../../icon/src/IconConfigProvider'
|
|
||||||
import { NBaseClear } from '../../_base'
|
|
||||||
import { useTheme, useLocale, useFormItem, useConfig } from '../../_mixins'
|
|
||||||
import { call, createKey } from '../../_utils'
|
|
||||||
import { inputLight } from '../styles'
|
|
||||||
import style from './styles/input.cssr.js'
|
|
||||||
|
|
||||||
function createMethods (
|
|
||||||
props,
|
|
||||||
formItem,
|
|
||||||
{
|
|
||||||
mergedValueRef,
|
|
||||||
uncontrolledValueRef,
|
|
||||||
isComposingRef,
|
|
||||||
focusedRef,
|
|
||||||
hoverRef,
|
|
||||||
activatedRef,
|
|
||||||
wrapperRef,
|
|
||||||
inputRef,
|
|
||||||
input2Ref,
|
|
||||||
textareaRef,
|
|
||||||
textareaMirrorRef
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const vm = getCurrentInstance().proxy
|
|
||||||
const doInput = (value) => {
|
|
||||||
const { 'onUpdate:value': onUpdateValue, onInput } = props
|
|
||||||
const { nTriggerFormInput } = formItem
|
|
||||||
if (onUpdateValue) call(onUpdateValue, value)
|
|
||||||
if (onInput) call(onInput, value)
|
|
||||||
uncontrolledValueRef.value = value
|
|
||||||
nTriggerFormInput()
|
|
||||||
}
|
|
||||||
const doChange = (value) => {
|
|
||||||
const { onChange } = props
|
|
||||||
const { nTriggerFormChange } = formItem
|
|
||||||
if (onChange) call(onChange, value)
|
|
||||||
uncontrolledValueRef.value = value
|
|
||||||
nTriggerFormChange()
|
|
||||||
}
|
|
||||||
const doBlur = (e) => {
|
|
||||||
const { onBlur } = props
|
|
||||||
const { nTriggerFormBlur } = formItem
|
|
||||||
if (onBlur) call(onBlur, e)
|
|
||||||
nTriggerFormBlur()
|
|
||||||
}
|
|
||||||
const doFocus = (e) => {
|
|
||||||
const { onFocus } = props
|
|
||||||
const { nTriggerFormFocus } = formItem
|
|
||||||
if (onFocus) call(onFocus, e)
|
|
||||||
nTriggerFormFocus()
|
|
||||||
}
|
|
||||||
const doClear = (...args) => {
|
|
||||||
const { onClear } = props
|
|
||||||
if (onClear) call(onClear, ...args)
|
|
||||||
}
|
|
||||||
const doInputBlur = (e) => {
|
|
||||||
const { onInputBlur } = props
|
|
||||||
if (onInputBlur) call(onInputBlur, e)
|
|
||||||
}
|
|
||||||
const doInputFocus = (e) => {
|
|
||||||
const { onInputFocus } = props
|
|
||||||
if (onInputFocus) call(onInputFocus, e)
|
|
||||||
}
|
|
||||||
const doDeactivate = () => {
|
|
||||||
const { onDeactivate } = props
|
|
||||||
if (onDeactivate) call(onDeactivate)
|
|
||||||
}
|
|
||||||
const doActivate = () => {
|
|
||||||
const { onActivate } = props
|
|
||||||
if (onActivate) call(onActivate)
|
|
||||||
}
|
|
||||||
const doKeyUp = (e) => {
|
|
||||||
const { onKeyUp } = props
|
|
||||||
if (onKeyUp) call(onKeyUp, e)
|
|
||||||
}
|
|
||||||
const doClick = (e) => {
|
|
||||||
const { onClick } = props
|
|
||||||
if (onClick) call(onClick, e)
|
|
||||||
}
|
|
||||||
const doWrapperFocus = (e) => {
|
|
||||||
const { onWrapperFocus } = props
|
|
||||||
if (onWrapperFocus) call(onWrapperFocus, e)
|
|
||||||
}
|
|
||||||
const doWrapperBlur = (e) => {
|
|
||||||
const { onWrapperBlur } = props
|
|
||||||
if (onWrapperBlur) call(onWrapperBlur, e)
|
|
||||||
}
|
|
||||||
// methods
|
|
||||||
const handleCompositionStart = () => {
|
|
||||||
isComposingRef.value = true
|
|
||||||
}
|
|
||||||
const handleCompositionEnd = (e) => {
|
|
||||||
isComposingRef.value = false
|
|
||||||
if (e.target === input2Ref.value) {
|
|
||||||
handleInput(e, 1)
|
|
||||||
} else {
|
|
||||||
handleInput(e, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleInput = (e, index, event = 'input') => {
|
|
||||||
if (isComposingRef.value) return
|
|
||||||
const changedValue = e.target.value
|
|
||||||
if (!props.pair) {
|
|
||||||
event === 'input' ? doInput(changedValue) : doChange(changedValue)
|
|
||||||
} else {
|
|
||||||
let { value } = mergedValueRef
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
value = [null, null]
|
|
||||||
} else {
|
|
||||||
value = [...value]
|
|
||||||
}
|
|
||||||
value[index] = changedValue
|
|
||||||
event === 'input' ? doInput(value) : doChange(value)
|
|
||||||
}
|
|
||||||
// force update to sync input's view with value
|
|
||||||
// if not set, after input, input value won't sync with dom input value
|
|
||||||
vm.$forceUpdate()
|
|
||||||
}
|
|
||||||
const handleInputBlur = (e) => {
|
|
||||||
doInputBlur(e)
|
|
||||||
if (e.relatedTarget === wrapperRef.value) {
|
|
||||||
doDeactivate()
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
e.relatedTarget !== null &&
|
|
||||||
(e.relatedTarget === inputRef.value ||
|
|
||||||
e.relatedTarget === input2Ref.value ||
|
|
||||||
e.relatedTarget === textareaRef.value)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
activatedRef.value = false
|
|
||||||
}
|
|
||||||
dealWithEvent(e, 'blur')
|
|
||||||
}
|
|
||||||
const handleInputFocus = (e) => {
|
|
||||||
doInputFocus(e)
|
|
||||||
focusedRef.value = true
|
|
||||||
activatedRef.value = true
|
|
||||||
doActivate()
|
|
||||||
dealWithEvent(e, 'focus')
|
|
||||||
}
|
|
||||||
const handleWrapperBlur = (e) => {
|
|
||||||
if (props.passivelyActivated) {
|
|
||||||
doWrapperBlur(e)
|
|
||||||
dealWithEvent(e, 'blur')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleWrapperFocus = (e) => {
|
|
||||||
if (props.passivelyActivated) {
|
|
||||||
focusedRef.value = true
|
|
||||||
doWrapperFocus(e)
|
|
||||||
dealWithEvent(e, 'focus')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const dealWithEvent = (e, type) => {
|
|
||||||
if (
|
|
||||||
e.relatedTarget !== null &&
|
|
||||||
(e.relatedTarget === inputRef.value ||
|
|
||||||
e.relatedTarget === input2Ref.value ||
|
|
||||||
e.relatedTarget === textareaRef.value ||
|
|
||||||
e.relatedTarget === wrapperRef.value)
|
|
||||||
) {
|
|
||||||
/**
|
|
||||||
* activeElement transfer inside the input, do nothing
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
if (type === 'focus') {
|
|
||||||
doFocus(e)
|
|
||||||
focusedRef.value = true
|
|
||||||
} else if (type === 'blur') {
|
|
||||||
doBlur(e)
|
|
||||||
focusedRef.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleKeyUp = (e) => {
|
|
||||||
doKeyUp(e)
|
|
||||||
}
|
|
||||||
const handleChange = (e, index) => handleInput(e, index, 'change')
|
|
||||||
const handleClick = (e) => {
|
|
||||||
doClick(e)
|
|
||||||
}
|
|
||||||
const handleClear = (e) => {
|
|
||||||
doClear(e)
|
|
||||||
if (props.pair) {
|
|
||||||
doInput([])
|
|
||||||
} else {
|
|
||||||
doInput('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleMouseEnter = () => {
|
|
||||||
hoverRef.value = true
|
|
||||||
}
|
|
||||||
const handleMouseLeave = () => {
|
|
||||||
hoverRef.value = false
|
|
||||||
}
|
|
||||||
const handleWrapperKeyDownEnter = (e) => {
|
|
||||||
if (props.passivelyActivated) {
|
|
||||||
const { value: focused } = activatedRef
|
|
||||||
if (focused) {
|
|
||||||
if (props.deactivateOnEnter) {
|
|
||||||
handleWrapperKeyDownEsc()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
|
||||||
if (props.type === 'textarea') {
|
|
||||||
textareaRef.value.focus()
|
|
||||||
} else {
|
|
||||||
inputRef.value.focus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleWrapperKeyDownEsc = () => {
|
|
||||||
if (props.passivelyActivated) {
|
|
||||||
activatedRef.value = false
|
|
||||||
nextTick(() => {
|
|
||||||
wrapperRef.value.focus()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
doInput,
|
|
||||||
doChange,
|
|
||||||
doFocus,
|
|
||||||
doBlur,
|
|
||||||
doClear,
|
|
||||||
doWrapperFocus,
|
|
||||||
doWrapperBlur,
|
|
||||||
doInputFocus,
|
|
||||||
doInputBlur,
|
|
||||||
doActivate,
|
|
||||||
doDeactivate,
|
|
||||||
doClick,
|
|
||||||
doKeyUp,
|
|
||||||
handleCompositionStart,
|
|
||||||
handleCompositionEnd,
|
|
||||||
handleInput,
|
|
||||||
handleInputBlur,
|
|
||||||
handleInputFocus,
|
|
||||||
handleWrapperBlur,
|
|
||||||
handleWrapperFocus,
|
|
||||||
handleMouseEnter,
|
|
||||||
handleMouseLeave,
|
|
||||||
handleKeyUp,
|
|
||||||
handleChange,
|
|
||||||
handleClick,
|
|
||||||
handleClear,
|
|
||||||
handleWrapperKeyDownEnter,
|
|
||||||
handleWrapperKeyDownEsc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Input',
|
|
||||||
components: {
|
|
||||||
NIconConfigProvider,
|
|
||||||
NBaseClear
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
...useTheme.props,
|
|
||||||
bordered: {
|
|
||||||
type: Boolean,
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: 'text'
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: [Array, String],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
defaultValue: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
validator (value) {
|
|
||||||
return ['small', 'medium', 'large'].includes(value)
|
|
||||||
},
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
rows: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: 3
|
|
||||||
},
|
|
||||||
round: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
minlength: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
maxlength: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
clearable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
autosize: {
|
|
||||||
type: [Boolean, Object],
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
showWordLimit: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
pair: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
separator: {
|
|
||||||
type: String,
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
readonly: {
|
|
||||||
type: [String, Boolean],
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
forceFocus: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
passivelyActivated: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
stateful: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
autofocus: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
onInput: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onFocus: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onBlur: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onClick: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onChange: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onKeyUp: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onClear: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
// eslint-disable-next-line vue/prop-name-casing
|
|
||||||
'onUpdate:value': {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
/** private */
|
|
||||||
textDecoration: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
attrSize: {
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
onInputBlur: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onInputFocus: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onDeactivate: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onActivate: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onWrapperFocus: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
onWrapperBlur: {
|
|
||||||
type: [Function, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
deactivateOnEnter: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup (props) {
|
|
||||||
const themeRef = useTheme('Input', 'Input', style, inputLight, props)
|
|
||||||
// dom refs
|
|
||||||
const wrapperRef = ref(null)
|
|
||||||
const textareaRef = ref(null)
|
|
||||||
const textareaMirrorRef = ref(null)
|
|
||||||
const inputRef = ref(null)
|
|
||||||
const input2Ref = ref(null)
|
|
||||||
// local
|
|
||||||
const { locale } = useLocale('Input')
|
|
||||||
// value
|
|
||||||
const uncontrolledValueRef = ref(props.defaultValue)
|
|
||||||
const controlledValueRef = toRef(props, 'value')
|
|
||||||
const mergedValueRef = useMergedState(
|
|
||||||
controlledValueRef,
|
|
||||||
uncontrolledValueRef
|
|
||||||
)
|
|
||||||
// form-item
|
|
||||||
const formItem = useFormItem(props)
|
|
||||||
const { mergedSize: mergedSizeRef } = formItem
|
|
||||||
// states
|
|
||||||
const focusedRef = ref(false)
|
|
||||||
const hoverRef = ref(false)
|
|
||||||
const isComposingRef = ref(false)
|
|
||||||
const activatedRef = ref(false)
|
|
||||||
// placeholder
|
|
||||||
const mergedPlaceholderRef = computed(() => {
|
|
||||||
const { placeholder, pair } = props
|
|
||||||
if (pair) {
|
|
||||||
if (Array.isArray(placeholder)) {
|
|
||||||
return placeholder
|
|
||||||
} else {
|
|
||||||
return [placeholder, placeholder]
|
|
||||||
}
|
|
||||||
} else if (placeholder === undefined) {
|
|
||||||
return [locale.value.placeholder]
|
|
||||||
} else {
|
|
||||||
return [placeholder]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const showPlaceholder1Ref = computed(() => {
|
|
||||||
const { value: isComposing } = isComposingRef
|
|
||||||
const { value: mergedValue } = mergedValueRef
|
|
||||||
const { value: mergedPlaceholder } = mergedPlaceholderRef
|
|
||||||
return (
|
|
||||||
!isComposing &&
|
|
||||||
(!mergedValue || (Array.isArray(mergedValue) && !mergedValue[0])) &&
|
|
||||||
mergedPlaceholder[0]
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const showPlaceholder2Ref = computed(() => {
|
|
||||||
const { value: isComposing } = isComposingRef
|
|
||||||
const { value: mergedValue } = mergedValueRef
|
|
||||||
const { value: mergedPlaceholder } = mergedPlaceholderRef
|
|
||||||
return (
|
|
||||||
!isComposing &&
|
|
||||||
mergedPlaceholder[1] &&
|
|
||||||
(!mergedValue || (Array.isArray(mergedValue) && !mergedValue[1]))
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const showTextareaPlaceholderRef = computed(() => {
|
|
||||||
return (
|
|
||||||
props.type === 'textarea' &&
|
|
||||||
!isComposingRef.value &&
|
|
||||||
!mergedValueRef.value &&
|
|
||||||
mergedPlaceholderRef.value
|
|
||||||
)
|
|
||||||
})
|
|
||||||
// clear
|
|
||||||
const showClearButton = computed(() => {
|
|
||||||
if (
|
|
||||||
props.disabled ||
|
|
||||||
!props.clearable ||
|
|
||||||
(!mergedFocusRef.value && !hoverRef.value)
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const { value: mergedValue } = mergedValueRef
|
|
||||||
const { value: mergedFocus } = mergedFocusRef
|
|
||||||
if (props.pair) {
|
|
||||||
return (
|
|
||||||
!!(
|
|
||||||
Array.isArray(mergedValue) &&
|
|
||||||
(mergedValue[0] || mergedValue[1])
|
|
||||||
) &&
|
|
||||||
(hoverRef.value || mergedFocus)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return !!mergedValue && (hoverRef.value || mergedFocus)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// focus
|
|
||||||
const mergedFocusRef = computed(() => {
|
|
||||||
return props.forceFocus || focusedRef.value
|
|
||||||
})
|
|
||||||
// text-decoration
|
|
||||||
const textDecorationStyleRef = computed(() => {
|
|
||||||
const { textDecoration } = props
|
|
||||||
if (!textDecoration) return ['', '']
|
|
||||||
if (Array.isArray(textDecoration)) {
|
|
||||||
return textDecoration.map((v) => ({
|
|
||||||
textDecoration: v
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
textDecoration
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
// textarea autosize
|
|
||||||
const updateTextAreaStyle = () => {
|
|
||||||
if (props.type === 'textarea') {
|
|
||||||
const { autosize } = props
|
|
||||||
if (!autosize) return
|
|
||||||
const {
|
|
||||||
paddingTop: stylePaddingTop,
|
|
||||||
paddingBottom: stylePaddingBottom,
|
|
||||||
lineHeight: styleLineHeight
|
|
||||||
} = window.getComputedStyle(textareaRef.value)
|
|
||||||
const paddingTop = Number(stylePaddingTop.slice(0, -2))
|
|
||||||
const paddingBottom = Number(stylePaddingBottom.slice(0, -2))
|
|
||||||
const lineHeight = Number(styleLineHeight.slice(0, -2))
|
|
||||||
if (autosize.minRows) {
|
|
||||||
const minRows = Math.max(autosize.minRows, 1)
|
|
||||||
const styleMinHeight =
|
|
||||||
paddingTop + paddingBottom + lineHeight * minRows + 'px'
|
|
||||||
textareaMirrorRef.value.style.minHeight = styleMinHeight
|
|
||||||
}
|
|
||||||
if (autosize.maxRows) {
|
|
||||||
const maxRows = Math.max(autosize.maxRows, autosize.minRows, 1)
|
|
||||||
const styleMaxHeight =
|
|
||||||
paddingTop + paddingBottom + lineHeight * maxRows + 'px'
|
|
||||||
textareaMirrorRef.value.style.maxHeight = styleMaxHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
watch([mergedValueRef, mergedSizeRef], () => {
|
|
||||||
nextTick(updateTextAreaStyle)
|
|
||||||
})
|
|
||||||
onMounted(updateTextAreaStyle)
|
|
||||||
// other methods
|
|
||||||
const methods = createMethods(props, formItem, {
|
|
||||||
mergedValueRef,
|
|
||||||
uncontrolledValueRef,
|
|
||||||
isComposingRef,
|
|
||||||
focusedRef,
|
|
||||||
hoverRef,
|
|
||||||
activatedRef,
|
|
||||||
wrapperRef,
|
|
||||||
inputRef,
|
|
||||||
input2Ref,
|
|
||||||
textareaRef,
|
|
||||||
textareaMirrorRef
|
|
||||||
})
|
|
||||||
const focus = () => {
|
|
||||||
if (props.disabled) return
|
|
||||||
if (props.passivelyActivated) {
|
|
||||||
wrapperRef.value.focus()
|
|
||||||
} else {
|
|
||||||
if (textareaRef.value) textareaRef.value.focus()
|
|
||||||
else if (inputRef.value) inputRef.value.focus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const blur = () => {
|
|
||||||
if (wrapperRef.value.contains(document.activeElement)) {
|
|
||||||
document.activeElement.blur()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const activate = () => {
|
|
||||||
if (props.disabled) return
|
|
||||||
if (textareaRef.value) textareaRef.value.focus()
|
|
||||||
else if (inputRef.value) inputRef.value.focus()
|
|
||||||
}
|
|
||||||
const deactivate = () => {
|
|
||||||
if (
|
|
||||||
wrapperRef.value.contains(document.activeElement) &&
|
|
||||||
wrapperRef.value !== document.activeElement
|
|
||||||
) {
|
|
||||||
methods.handleWrapperKeyDownEsc()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
// DOM ref
|
|
||||||
wrapperRef,
|
|
||||||
inputRef,
|
|
||||||
input2Ref,
|
|
||||||
textareaRef,
|
|
||||||
textareaMirrorRef,
|
|
||||||
// value
|
|
||||||
uncontrolledValue: uncontrolledValueRef,
|
|
||||||
mergedValue: mergedValueRef,
|
|
||||||
mergedPlaceholder: mergedPlaceholderRef,
|
|
||||||
showPlaceholder1: showPlaceholder1Ref,
|
|
||||||
showPlaceholder2: showPlaceholder2Ref,
|
|
||||||
showTextareaPlaceholder: showTextareaPlaceholderRef,
|
|
||||||
mergedFocus: mergedFocusRef,
|
|
||||||
isComposing: isComposingRef,
|
|
||||||
activated: activatedRef,
|
|
||||||
showClearButton,
|
|
||||||
mergedSize: mergedSizeRef,
|
|
||||||
textDecorationStyle: textDecorationStyleRef,
|
|
||||||
// methods
|
|
||||||
focus,
|
|
||||||
blur,
|
|
||||||
deactivate,
|
|
||||||
activate,
|
|
||||||
...methods,
|
|
||||||
...useConfig(props),
|
|
||||||
mergedTheme: themeRef,
|
|
||||||
cssVars: computed(() => {
|
|
||||||
const { value: size } = mergedSizeRef
|
|
||||||
const {
|
|
||||||
common: { cubicBezierEaseInOut },
|
|
||||||
self: {
|
|
||||||
color,
|
|
||||||
borderRadius,
|
|
||||||
paddingLeft,
|
|
||||||
paddingRight,
|
|
||||||
textColor,
|
|
||||||
caretColor,
|
|
||||||
textDecorationColor,
|
|
||||||
border,
|
|
||||||
borderDisabled,
|
|
||||||
borderHover,
|
|
||||||
borderFocus,
|
|
||||||
placeholderColor,
|
|
||||||
placeholderColorDisabled,
|
|
||||||
lineHeightTextarea,
|
|
||||||
colorDisabled,
|
|
||||||
colorFocus,
|
|
||||||
textColorDisabled,
|
|
||||||
boxShadowFocus,
|
|
||||||
iconSize,
|
|
||||||
colorFocusWarning,
|
|
||||||
boxShadowFocusWarning,
|
|
||||||
boxShadowHoverWarning,
|
|
||||||
borderWarning,
|
|
||||||
borderFocusWarning,
|
|
||||||
borderHoverWarning,
|
|
||||||
colorFocusError,
|
|
||||||
boxShadowFocusError,
|
|
||||||
boxShadowHoverError,
|
|
||||||
borderError,
|
|
||||||
borderFocusError,
|
|
||||||
borderHoverError,
|
|
||||||
[createKey('fontSize', size)]: fontSize,
|
|
||||||
[createKey('height', size)]: height
|
|
||||||
}
|
|
||||||
} = themeRef.value
|
|
||||||
return {
|
|
||||||
'--bezier': cubicBezierEaseInOut,
|
|
||||||
'--color': color,
|
|
||||||
'--font-size': fontSize,
|
|
||||||
'--border-radius': borderRadius,
|
|
||||||
'--height': height,
|
|
||||||
'--padding-left': paddingLeft,
|
|
||||||
'--padding-right': paddingRight,
|
|
||||||
'--text-color': textColor,
|
|
||||||
'--caret-color': caretColor,
|
|
||||||
'--text-decoration-color': textDecorationColor,
|
|
||||||
'--border': border,
|
|
||||||
'--border-disabled': borderDisabled,
|
|
||||||
'--border-hover': borderHover,
|
|
||||||
'--border-focus': borderFocus,
|
|
||||||
'--placeholder-color': placeholderColor,
|
|
||||||
'--placeholder-color-disabled': placeholderColorDisabled,
|
|
||||||
'--icon-size': iconSize,
|
|
||||||
'--line-height-textarea': lineHeightTextarea,
|
|
||||||
'--color-disabled': colorDisabled,
|
|
||||||
'--color-focus': colorFocus,
|
|
||||||
'--text-color-disabled': textColorDisabled,
|
|
||||||
'--box-shadow-focus': boxShadowFocus,
|
|
||||||
// form warning
|
|
||||||
'--color-focus-warning': colorFocusWarning,
|
|
||||||
'--box-shadow-focus-warning': boxShadowFocusWarning,
|
|
||||||
'--box-shadow-hover-warning': boxShadowHoverWarning,
|
|
||||||
'--border-warning': borderWarning,
|
|
||||||
'--border-focus-warning': borderFocusWarning,
|
|
||||||
'--border-hover-warning': borderHoverWarning,
|
|
||||||
// form error
|
|
||||||
'--color-focus-error': colorFocusError,
|
|
||||||
'--box-shadow-focus-error': boxShadowFocusError,
|
|
||||||
'--box-shadow-hover-error': boxShadowHoverError,
|
|
||||||
'--border-error': borderError,
|
|
||||||
'--border-focus-error': borderFocusError,
|
|
||||||
'--border-hover-error': borderHoverError
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
13
src/input/src/InputGroup.tsx
Normal file
13
src/input/src/InputGroup.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { h, defineComponent, renderSlot } from 'vue'
|
||||||
|
import { useStyle } from '../../_mixins'
|
||||||
|
import style from './styles/input-group.cssr'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'InputGroup',
|
||||||
|
setup () {
|
||||||
|
useStyle('InputGroup', style)
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
return <div class="n-input-group">{renderSlot(this.$slots, 'default')}</div>
|
||||||
|
}
|
||||||
|
})
|
@ -1,18 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="n-input-group">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from 'vue'
|
|
||||||
import { useStyle } from '../../_mixins'
|
|
||||||
import style from './styles/input-group.cssr.js'
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'InputGroup',
|
|
||||||
setup (props) {
|
|
||||||
useStyle('InputGroup', style)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -1,27 +1,18 @@
|
|||||||
<template>
|
import { computed, defineComponent, renderSlot, h, PropType } from 'vue'
|
||||||
<div
|
|
||||||
class="n-input-group-label"
|
|
||||||
:class="`n-input-group-label--${size}-size`"
|
|
||||||
:style="cssVars"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
<div class="n-input-group-label__border" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { computed, defineComponent } from 'vue'
|
|
||||||
import { useTheme } from '../../_mixins'
|
import { useTheme } from '../../_mixins'
|
||||||
|
import type { ThemeProps } from '../../_mixins'
|
||||||
import { createKey } from '../../_utils'
|
import { createKey } from '../../_utils'
|
||||||
import { inputLight } from '../styles'
|
import { inputLight } from '../styles'
|
||||||
import style from './styles/input-group-label.cssr.js'
|
import type { InputTheme } from '../styles'
|
||||||
|
import style from './styles/input-group-label.cssr'
|
||||||
|
import type { Size } from './interface'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'InputGroupLabel',
|
name: 'InputGroupLabel',
|
||||||
props: {
|
props: {
|
||||||
...useTheme.props,
|
...(useTheme.props as ThemeProps<InputTheme>),
|
||||||
size: {
|
size: {
|
||||||
type: String,
|
type: String as PropType<Size>,
|
||||||
default: 'medium'
|
default: 'medium'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -43,8 +34,8 @@ export default defineComponent({
|
|||||||
borderRadius,
|
borderRadius,
|
||||||
textColor,
|
textColor,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
fontSize,
|
|
||||||
border,
|
border,
|
||||||
|
[createKey('fontSize', size)]: fontSize,
|
||||||
[createKey('height', size)]: height
|
[createKey('height', size)]: height
|
||||||
}
|
}
|
||||||
} = themeRef.value
|
} = themeRef.value
|
||||||
@ -60,6 +51,13 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div class="n-input-group-label" style={this.cssVars as any}>
|
||||||
|
{renderSlot(this.$slots, 'default')}
|
||||||
|
<div class="n-input-group-label__border" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
|
1
src/input/src/interface.ts
Normal file
1
src/input/src/interface.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type Size = 'small' | 'medium' | 'large'
|
@ -22,7 +22,10 @@ import { cB, c, cE, cM, cNotM, insideFormItem } from '../../../_utils/cssr'
|
|||||||
// --color-disabled
|
// --color-disabled
|
||||||
// --color-focus
|
// --color-focus
|
||||||
// --box-shadow-focus
|
// --box-shadow-focus
|
||||||
// --icon-size
|
// --clear-color
|
||||||
|
// --clear-size
|
||||||
|
// --clear-color-hover
|
||||||
|
// --clear-color-pressed
|
||||||
export default c([
|
export default c([
|
||||||
cB('input', `
|
cB('input', `
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@ -241,7 +244,6 @@ export default c([
|
|||||||
}),
|
}),
|
||||||
c('&:hover', [
|
c('&:hover', [
|
||||||
cE('state-border', `
|
cE('state-border', `
|
||||||
box-shadow: var(--box-shadow-hover-${status});
|
|
||||||
border: var(--border-hover-${status});
|
border: var(--border-hover-${status});
|
||||||
`)
|
`)
|
||||||
]),
|
]),
|
@ -1,5 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
paddingLeft: '14px',
|
paddingLeft: '14px',
|
||||||
paddingRight: '8px',
|
paddingRight: '8px',
|
||||||
paddingIcon: '38px'
|
paddingIcon: '38px',
|
||||||
|
clearSize: '16px'
|
||||||
}
|
}
|
@ -1,14 +1,11 @@
|
|||||||
import commonVariables from './_common'
|
import commonVariables from './_common'
|
||||||
import { changeColor } from 'seemly'
|
import { changeColor, scaleColor } from 'seemly'
|
||||||
import { baseClearDark } from '../../_base/clear/styles'
|
|
||||||
import { commonDark } from '../../_styles/new-common'
|
import { commonDark } from '../../_styles/new-common'
|
||||||
|
import type { InputTheme } from './light'
|
||||||
|
|
||||||
export default {
|
const inputDark: InputTheme = {
|
||||||
name: 'Input',
|
name: 'Input',
|
||||||
common: commonDark,
|
common: commonDark,
|
||||||
peers: {
|
|
||||||
BaseClear: baseClearDark
|
|
||||||
},
|
|
||||||
self (vars) {
|
self (vars) {
|
||||||
const {
|
const {
|
||||||
textColor2Overlay,
|
textColor2Overlay,
|
||||||
@ -43,6 +40,7 @@ export default {
|
|||||||
fontSizeSmall,
|
fontSizeSmall,
|
||||||
fontSizeMedium,
|
fontSizeMedium,
|
||||||
fontSizeLarge,
|
fontSizeLarge,
|
||||||
|
lineHeight,
|
||||||
lineHeightTextarea: lineHeight,
|
lineHeightTextarea: lineHeight,
|
||||||
borderRadius,
|
borderRadius,
|
||||||
iconSize: '16px',
|
iconSize: '16px',
|
||||||
@ -78,7 +76,12 @@ export default {
|
|||||||
boxShadowFocusError: `0 0 8px 0 ${changeColor(errorColor, {
|
boxShadowFocusError: `0 0 8px 0 ${changeColor(errorColor, {
|
||||||
alpha: 0.3
|
alpha: 0.3
|
||||||
})}`,
|
})}`,
|
||||||
caretColorError: errorColor
|
caretColorError: errorColor,
|
||||||
|
clearColor: textColor4Overlay,
|
||||||
|
clearColorHover: scaleColor(textColor4Overlay, { alpha: 1.25 }),
|
||||||
|
clearColorPressed: scaleColor(textColor4Overlay, { alpha: 0.75 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default inputDark
|
@ -1,2 +0,0 @@
|
|||||||
export { default as inputDark } from './dark.js'
|
|
||||||
export { default as inputLight } from './light.js'
|
|
3
src/input/styles/index.ts
Normal file
3
src/input/styles/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { default as inputDark } from './dark'
|
||||||
|
export { default as inputLight } from './light'
|
||||||
|
export type { InputTheme, InputThemeVars } from './light'
|
@ -1,86 +0,0 @@
|
|||||||
import commonVariables from './_common'
|
|
||||||
import { changeColor } from 'seemly'
|
|
||||||
import { baseClearLight } from '../../_base/clear/styles'
|
|
||||||
import { commonLight } from '../../_styles/new-common'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Input',
|
|
||||||
common: commonLight,
|
|
||||||
peers: {
|
|
||||||
BaseClear: baseClearLight
|
|
||||||
},
|
|
||||||
self (vars) {
|
|
||||||
const {
|
|
||||||
textColor2,
|
|
||||||
textColor4,
|
|
||||||
textColor5,
|
|
||||||
primaryColor,
|
|
||||||
primaryColorHover,
|
|
||||||
inputColor,
|
|
||||||
inputColorDisabled,
|
|
||||||
borderColor,
|
|
||||||
warningColor,
|
|
||||||
warningColorHover,
|
|
||||||
errorColor,
|
|
||||||
errorColorHover,
|
|
||||||
borderRadius,
|
|
||||||
lineHeight,
|
|
||||||
fontSizeTiny,
|
|
||||||
fontSizeSmall,
|
|
||||||
fontSizeMedium,
|
|
||||||
fontSizeLarge,
|
|
||||||
heightTiny,
|
|
||||||
heightSmall,
|
|
||||||
heightMedium,
|
|
||||||
heightLarge,
|
|
||||||
actionColor
|
|
||||||
} = vars
|
|
||||||
return {
|
|
||||||
...commonVariables,
|
|
||||||
heightTiny,
|
|
||||||
heightSmall,
|
|
||||||
heightMedium,
|
|
||||||
heightLarge,
|
|
||||||
fontSizeTiny,
|
|
||||||
fontSizeSmall,
|
|
||||||
fontSizeMedium,
|
|
||||||
fontSizeLarge,
|
|
||||||
lineHeightTextarea: lineHeight,
|
|
||||||
borderRadius,
|
|
||||||
iconSize: '16px',
|
|
||||||
groupLabelColor: actionColor,
|
|
||||||
textColor: textColor2,
|
|
||||||
textColorDisabled: textColor4,
|
|
||||||
textDecorationColor: textColor2,
|
|
||||||
caretColor: primaryColor,
|
|
||||||
placeholderColor: textColor4,
|
|
||||||
placeholderColorDisabled: textColor5,
|
|
||||||
color: inputColor,
|
|
||||||
colorDisabled: inputColorDisabled,
|
|
||||||
colorFocus: inputColor,
|
|
||||||
border: `1px solid ${borderColor}`,
|
|
||||||
borderHover: `1px solid ${primaryColorHover}`,
|
|
||||||
borderDisabled: `1px solid ${borderColor}`,
|
|
||||||
borderFocus: `1px solid ${primaryColorHover}`,
|
|
||||||
boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, { alpha: 0.2 })}`,
|
|
||||||
// warning
|
|
||||||
borderWarning: `1px solid ${warningColor}`,
|
|
||||||
borderHoverWarning: `1px solid ${warningColorHover}`,
|
|
||||||
colorFocusWarning: inputColor,
|
|
||||||
borderFocusWarning: `1px solid ${warningColorHover}`,
|
|
||||||
boxShadowFocusWarning: `0 0 0 2px ${changeColor(warningColor, {
|
|
||||||
alpha: 0.2
|
|
||||||
})}`,
|
|
||||||
caretColorWarning: warningColor,
|
|
||||||
// error
|
|
||||||
borderError: `1px solid ${errorColor}`,
|
|
||||||
borderHoverError: `1px solid ${errorColorHover}`,
|
|
||||||
colorFocusError: inputColor,
|
|
||||||
borderFocusError: `1px solid ${errorColorHover}`,
|
|
||||||
boxShadowFocusError: `0 0 0 2px ${changeColor(errorColor, {
|
|
||||||
alpha: 0.2
|
|
||||||
})}`,
|
|
||||||
caretColorError: errorColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
95
src/input/styles/light.ts
Normal file
95
src/input/styles/light.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import commonVariables from './_common'
|
||||||
|
import { changeColor, scaleColor } from 'seemly'
|
||||||
|
import { commonLight } from '../../_styles/new-common'
|
||||||
|
import type { ThemeCommonVars } from '../../_styles/new-common'
|
||||||
|
import type { Theme } from '../../_mixins'
|
||||||
|
|
||||||
|
const self = (vars: ThemeCommonVars) => {
|
||||||
|
const {
|
||||||
|
textColor2,
|
||||||
|
textColor4,
|
||||||
|
textColor5,
|
||||||
|
primaryColor,
|
||||||
|
primaryColorHover,
|
||||||
|
inputColor,
|
||||||
|
inputColorDisabled,
|
||||||
|
borderColor,
|
||||||
|
warningColor,
|
||||||
|
warningColorHover,
|
||||||
|
errorColor,
|
||||||
|
errorColorHover,
|
||||||
|
borderRadius,
|
||||||
|
lineHeight,
|
||||||
|
fontSizeTiny,
|
||||||
|
fontSizeSmall,
|
||||||
|
fontSizeMedium,
|
||||||
|
fontSizeLarge,
|
||||||
|
heightTiny,
|
||||||
|
heightSmall,
|
||||||
|
heightMedium,
|
||||||
|
heightLarge,
|
||||||
|
actionColor
|
||||||
|
} = vars
|
||||||
|
return {
|
||||||
|
...commonVariables,
|
||||||
|
heightTiny,
|
||||||
|
heightSmall,
|
||||||
|
heightMedium,
|
||||||
|
heightLarge,
|
||||||
|
fontSizeTiny,
|
||||||
|
fontSizeSmall,
|
||||||
|
fontSizeMedium,
|
||||||
|
fontSizeLarge,
|
||||||
|
lineHeight,
|
||||||
|
lineHeightTextarea: lineHeight,
|
||||||
|
borderRadius,
|
||||||
|
iconSize: '16px',
|
||||||
|
groupLabelColor: actionColor,
|
||||||
|
textColor: textColor2,
|
||||||
|
textColorDisabled: textColor4,
|
||||||
|
textDecorationColor: textColor2,
|
||||||
|
caretColor: primaryColor,
|
||||||
|
placeholderColor: textColor4,
|
||||||
|
placeholderColorDisabled: textColor5,
|
||||||
|
color: inputColor,
|
||||||
|
colorDisabled: inputColorDisabled,
|
||||||
|
colorFocus: inputColor,
|
||||||
|
border: `1px solid ${borderColor}`,
|
||||||
|
borderHover: `1px solid ${primaryColorHover}`,
|
||||||
|
borderDisabled: `1px solid ${borderColor}`,
|
||||||
|
borderFocus: `1px solid ${primaryColorHover}`,
|
||||||
|
boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, { alpha: 0.2 })}`,
|
||||||
|
// warning
|
||||||
|
borderWarning: `1px solid ${warningColor}`,
|
||||||
|
borderHoverWarning: `1px solid ${warningColorHover}`,
|
||||||
|
colorFocusWarning: inputColor,
|
||||||
|
borderFocusWarning: `1px solid ${warningColorHover}`,
|
||||||
|
boxShadowFocusWarning: `0 0 0 2px ${changeColor(warningColor, {
|
||||||
|
alpha: 0.2
|
||||||
|
})}`,
|
||||||
|
caretColorWarning: warningColor,
|
||||||
|
// error
|
||||||
|
borderError: `1px solid ${errorColor}`,
|
||||||
|
borderHoverError: `1px solid ${errorColorHover}`,
|
||||||
|
colorFocusError: inputColor,
|
||||||
|
borderFocusError: `1px solid ${errorColorHover}`,
|
||||||
|
boxShadowFocusError: `0 0 0 2px ${changeColor(errorColor, {
|
||||||
|
alpha: 0.2
|
||||||
|
})}`,
|
||||||
|
caretColorError: errorColor,
|
||||||
|
clearColor: textColor4,
|
||||||
|
clearColorHover: scaleColor(textColor4, { lightness: 0.75 }),
|
||||||
|
clearColorPressed: scaleColor(textColor4, { lightness: 0.9 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InputThemeVars = ReturnType<typeof self>
|
||||||
|
|
||||||
|
const inputLight: Theme<InputThemeVars> = {
|
||||||
|
name: 'Input',
|
||||||
|
common: commonLight,
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
export default inputLight
|
||||||
|
export type InputTheme = typeof inputLight
|
Loading…
Reference in New Issue
Block a user