index.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import eventsMixin from '../helpers/mixins/eventsMixin'
  4. import styleToCssString from '../helpers/libs/styleToCssString'
  5. import { bound } from '../helpers/shared/bound'
  6. import { nativeInputProps } from './props'
  7. const defaultEvents = {
  8. onChange() {},
  9. onFocus() {},
  10. onBlur() {},
  11. onConfirm() {},
  12. onClear() {},
  13. onError() {},
  14. }
  15. baseComponent({
  16. behaviors: [eventsMixin({ defaultEvents })],
  17. relations: {
  18. '../field/index': {
  19. type: 'ancestor',
  20. },
  21. },
  22. properties: {
  23. ...nativeInputProps,
  24. prefixCls: {
  25. type: String,
  26. value: 'wux-input',
  27. },
  28. label: {
  29. type: String,
  30. value: '',
  31. },
  32. extra: {
  33. type: String,
  34. value: '',
  35. },
  36. defaultValue: {
  37. type: String,
  38. value: '',
  39. },
  40. value: {
  41. type: String,
  42. value: '',
  43. observer(newVal) {
  44. if (this.data.controlled) {
  45. this.updated(newVal)
  46. }
  47. },
  48. },
  49. controlled: {
  50. type: Boolean,
  51. value: false,
  52. },
  53. disabled: {
  54. type: Boolean,
  55. value: false,
  56. },
  57. readOnly: {
  58. type: Boolean,
  59. value: false,
  60. },
  61. clear: {
  62. type: Boolean,
  63. value: false,
  64. },
  65. error: {
  66. type: Boolean,
  67. value: false,
  68. },
  69. labelWrap: {
  70. type: Boolean,
  71. value: false,
  72. },
  73. requiredMark: {
  74. type: Boolean,
  75. value: false,
  76. },
  77. onlyShowClearWhenFocus: {
  78. type: Boolean,
  79. value: true,
  80. },
  81. min: {
  82. type: Number,
  83. value: null,
  84. },
  85. max: {
  86. type: Number,
  87. value: null,
  88. },
  89. visibilityToggle: {
  90. type: Boolean,
  91. value: false,
  92. },
  93. },
  94. data: {
  95. inputValue: '',
  96. inputFocus: false,
  97. shouldShowClear: false,
  98. internalPlaceholderStyle: '',
  99. internalVisible: false,
  100. },
  101. observers: {
  102. placeholderStyle(placeholderStyle) {
  103. this.setInternalPlaceholderStyle(placeholderStyle)
  104. },
  105. ['clear, disabled, readOnly, inputValue, inputFocus, onlyShowClearWhenFocus'](...args) {
  106. const [
  107. clear,
  108. disabled,
  109. readOnly,
  110. inputValue,
  111. inputFocus,
  112. onlyShowClearWhenFocus,
  113. ] = args
  114. this.setClear({
  115. clear,
  116. disabled,
  117. readOnly,
  118. inputValue,
  119. inputFocus,
  120. onlyShowClearWhenFocus,
  121. })
  122. },
  123. },
  124. computed: {
  125. classes: ['prefixCls, disabled, readOnly, inputFocus, error, labelWrap, requiredMark, internalVisible', function(prefixCls, disabled, readOnly, inputFocus, hasError, labelWrap, requiredMark, internalVisible) {
  126. const wrap = classNames(prefixCls, {
  127. [`${prefixCls}--focus`]: inputFocus,
  128. [`${prefixCls}--disabled`]: disabled,
  129. [`${prefixCls}--readonly`]: readOnly,
  130. [`${prefixCls}--error`]: hasError,
  131. })
  132. const label = classNames(`${prefixCls}__label`, {
  133. [`${prefixCls}__label--wrap`]: labelWrap,
  134. [`${prefixCls}__label--required`]: requiredMark,
  135. })
  136. const control = `${prefixCls}__control`
  137. const item = `${prefixCls}__item`
  138. const clear = `${prefixCls}__clear`
  139. const eye = classNames(`${prefixCls}__eye`, {
  140. [`${prefixCls}__eye--invisible`]: !internalVisible,
  141. })
  142. const error = `${prefixCls}__error`
  143. const extra = `${prefixCls}__extra`
  144. const keyboardAccessory = `${prefixCls}__keyboardAccessory`
  145. return {
  146. wrap,
  147. label,
  148. control,
  149. item,
  150. clear,
  151. eye,
  152. error,
  153. extra,
  154. keyboardAccessory,
  155. }
  156. }],
  157. },
  158. methods: {
  159. onInternalVisibleChange() {
  160. const { disabled } = this.data
  161. if (disabled) {
  162. return
  163. }
  164. const internalVisible = !this.data.internalVisible
  165. this.setData({
  166. internalVisible,
  167. })
  168. },
  169. setInternalPlaceholderStyle(placeholderStyle) {
  170. const internalPlaceholderStyle = styleToCssString(placeholderStyle)
  171. if (this.data.internalPlaceholderStyle !== internalPlaceholderStyle) {
  172. this.setData({
  173. internalPlaceholderStyle,
  174. })
  175. }
  176. },
  177. setClear(props) {
  178. const shouldShowClear = (() => {
  179. if (!props.clear || !props.inputValue || props.disabled || props.readOnly) return false
  180. if (props.onlyShowClearWhenFocus) {
  181. return props.inputFocus
  182. } else {
  183. return true
  184. }
  185. })()
  186. if (this.data.shouldShowClear !== shouldShowClear) {
  187. this.setData({
  188. shouldShowClear,
  189. })
  190. }
  191. },
  192. checkValue() {
  193. const props = this.data
  194. const { inputValue: value } = props
  195. let nextValue = value
  196. if (props.type === 'number' || props.type === 'digit') {
  197. nextValue =
  198. nextValue &&
  199. bound(
  200. parseFloat(nextValue),
  201. props.min !== null ? props.min : undefined,
  202. props.max !== null ? props.max : undefined
  203. ).toString()
  204. }
  205. if (nextValue !== value) {
  206. if (!this.data.controlled) {
  207. this.updated(nextValue)
  208. }
  209. this.triggerEvent('change', { value: nextValue })
  210. }
  211. },
  212. updated(inputValue) {
  213. if (this.hasFieldDecorator) return
  214. if (this.data.inputValue !== inputValue) {
  215. this.setData({ inputValue })
  216. }
  217. },
  218. onChange(e) {
  219. const { value } = e.detail
  220. if (!this.data.controlled) {
  221. this.updated(value)
  222. }
  223. this.triggerEvent('change', e.detail)
  224. },
  225. onFocus(e) {
  226. this.clearTimer()
  227. this.setData({
  228. inputFocus: true,
  229. })
  230. this.triggerEvent('focus', e.detail)
  231. },
  232. onBlur(e) {
  233. this.setTimer()
  234. this.checkValue()
  235. this.triggerEvent('blur', e.detail)
  236. },
  237. onConfirm(e) {
  238. this.triggerEvent('confirm', e.detail)
  239. },
  240. onKeyboardHeightChange(e) {
  241. this.triggerEvent('keyboardheightchange', e.detail)
  242. },
  243. onNicknameReview(e) {
  244. this.triggerEvent('nicknamereview', e.detail)
  245. },
  246. onClear() {
  247. const params = { value: '' }
  248. if (!this.data.controlled) {
  249. this.updated(params.value)
  250. }
  251. this.triggerEvent('change', params)
  252. this.triggerEvent('clear', params)
  253. },
  254. onError() {
  255. const { inputValue: value } = this.data
  256. this.triggerEvent('error', { value })
  257. },
  258. setTimer() {
  259. this.clearTimer()
  260. this.timeout = setTimeout(() => {
  261. this.setData({
  262. inputFocus: false,
  263. })
  264. }, 200)
  265. },
  266. clearTimer() {
  267. if (this.timeout) {
  268. clearTimeout(this.timeout)
  269. this.timeout = null
  270. }
  271. },
  272. },
  273. attached() {
  274. const { defaultValue, value, controlled, placeholderStyle } = this.data
  275. const inputValue = controlled ? value : defaultValue
  276. this.updated(inputValue)
  277. this.setClear({ ...this.data, inputValue })
  278. this.setInternalPlaceholderStyle(placeholderStyle)
  279. },
  280. })