Skip to content

Commit

Permalink
feat(search-bar): 新增组件
Browse files Browse the repository at this point in the history
  • Loading branch information
jimczj committed Sep 28, 2018
1 parent 04e08f8 commit 63acb61
Show file tree
Hide file tree
Showing 8 changed files with 456 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class App extends Component {
'pages/form/rate/index',
'pages/form/picker/index',
'pages/form/picker-view/index',
'pages/form/slider/index'
'pages/form/slider/index',
'pages/form/search-bar/index'
],
window: {
backgroundTextStyle: 'light',
Expand Down
19 changes: 19 additions & 0 deletions src/components/search-bar/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AtSearchBar Snap render AtSearchBar -- props actionName 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-147px;\\" class=\\"at-search-bar__action\\">actionName</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props disabled 1`] = `"<div class=\\"at-search-bar at-search-bar--fixed\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-35px;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props disabled 2`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" disabled type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-35px;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props focus 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:28px;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" focus maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:1;margin-right:0;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props maxlength 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-35px;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props placeholder 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\">placeholder</span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-35px;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props showActionButton 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:1;margin-right:0;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render AtSearchBar -- props value 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:28px;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: hidden;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"value\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: flex;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:1;margin-right:0;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
exports[`AtSearchBar Snap render initial AtSwitch 1`] = `"<div class=\\"at-search-bar\\"><div class=\\"at-search-bar__container\\"><div style=\\"width:100%;\\" class=\\"at-search-bar__placeholder_wrap\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-search\\"></span><span style=\\"visibility: visible;\\" class=\\"taro-text at-search-bar__placeholder\\"></span></div><input value=\\"\\" maxlength=\\"120\\" class=\\"weui-input at-search-bar__input\\" type=\\"search\\"/><div style=\\"display: none;\\" class=\\"at-search-bar__clear\\"><span style=\\"font-size:15px;color:#999;\\" class=\\"taro-text at-icon at-icon-close-circle\\"></span></div></div><div style=\\"opacity:0;margin-right:-35px;\\" class=\\"at-search-bar__action\\">取消</div></div>"`;
174 changes: 174 additions & 0 deletions src/components/search-bar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import Taro from '@tarojs/taro'
import { View, Text, Input } from '@tarojs/components'
import classNames from 'classnames'
import PropTypes from 'prop-types'

import AtIcon from '../../components/icon/index'
import AtComponent from '../../common/component'
import './index.scss'

const defaultFunc = () => { }

export default class AtSearchBar extends AtComponent {
constructor (props) {
super(...arguments)
this.state = {
isFocus: props.focus
}
}

static defaultProps = {
value: '',
placeholder: '',
maxlength: 120,
fixed: false,
focus: false,
disabled: false,
showActionButton: false,
actionName: '取消',
onChange: defaultFunc,
onFocus: defaultFunc,
onBlur: defaultFunc,
onConfirm: defaultFunc,
}

static propTypes = {
value: PropTypes.string,
placeholder: PropTypes.string,
maxlength: PropTypes.number,
fixed: PropTypes.bool,
focus: PropTypes.bool,
disabled: PropTypes.bool,
showActionButton: PropTypes.bool,
actionName: PropTypes.string,
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onConfirm: PropTypes.func,
onActionClick: PropTypes.func
}

handleFocus (e) {
this.setState({
isFocus: true
})
this.props.onFocus(e, ...arguments)
}

handleBlur (e) {
this.setState({
isFocus: false
})
this.props.onBlur(e, ...arguments)
}

handleChange (e) {
this.props.onChange(e.target.value, e, ...arguments)
}

handleClear (e) {
this.props.onChange('', e, ...arguments)
}

handleConfirm (e) {
this.props.onConfirm(e, ...arguments)
}

handleActionClick (e) {
if (!this.props.onActionClick) {
this.setState({
isFocus: false
})
this.handleClear(e)
} else {
this.props.onActionClick(e)
}
}

render () {
const {
value,
placeholder,
maxlength,
fixed,
focus,
disabled,
showActionButton,
actionName,
} = this.props
const { isFocus } = this.state

const placeholderStyle = {}
const actionStyle = {}
if (isFocus || (!isFocus && value)) {
placeholderStyle.width = `${(placeholder.length + 2) * 14}px`
actionStyle.opacity = 1
actionStyle.marginRight = `0`
} else if (!isFocus && !value) {
placeholderStyle.width = '100%'
actionStyle.opacity = 0
actionStyle.marginRight = `-${((actionName.length) * 14) + 7}px`
}
if (showActionButton) {
actionStyle.opacity = 1
actionStyle.marginRight = `0`
}
return (
<View
className={
classNames({
'at-search-bar': true,
'at-search-bar--fixed': fixed
})
}
>
<View className='at-search-bar__container'>
<View
className='at-search-bar__placeholder_wrap'
style={placeholderStyle}
>
<AtIcon value='search' size='15' color='#999' />
<Text
className='at-search-bar__placeholder'
style={
value.length
? 'visibility: hidden;'
: 'visibility: visible;'
}
>{placeholder}</Text>
</View>
<Input
className='at-search-bar__input'
type='search'
value={value}
focus={focus}
disabled={disabled}
maxlength={maxlength}
onInput={this.handleChange.bind(this)}
onFocus={this.handleFocus.bind(this)}
onBlur={this.handleBlur.bind(this)}
onConfirm={this.handleConfirm.bind(this)}
/>
<View
className='at-search-bar__clear'
style={
value.length
? 'display: flex;'
: 'display: none;'
}
onTouchStart={this.handleClear.bind(this)}
>
<AtIcon value='close-circle' size='15' color='#999' />
</View>
</View>
<View
onClick={this.handleActionClick.bind(this)}
className='at-search-bar__action'
style={actionStyle}
>
{actionName}
</View>
</View>
)
}
}
99 changes: 99 additions & 0 deletions src/components/search-bar/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@import '../../style/mixins/index.scss';
@import '../../style/theme/default.scss';
$height: 28PX;
$inputPadding: 25PX;
$fontSize: 14PX;

.at-search-bar {
display: flex;
align-items: center;
height: $height;
padding: $spacing-v-sm 0;
box-sizing: content-box;
background-color: $color-border-lighter;

&__container {
position: relative;
flex: 1;
overflow: hidden;
width: 100%;
margin: 0 $fontSize / 2;
height: $height;
background-color: #fff;
}

&__placeholder_wrap {
position: absolute;
top: 0;
left: 0;
z-index: 1;
opacity: 1;
display: flex;
align-self: center;
align-items: center;
justify-content: center;
vertical-align: middle;
width: 100%;
height: $height;
line-height: 0;
transition: width 0.3s;
}

&__placeholder {
margin-left: 10px;
color: $color-grey-2;
font-size: $fontSize;
}

&__input {
position: absolute;
width: 100%;
height: $height;
top: 0;
left: 0;
display: block;
font-size: $fontSize;
padding: 5PX $inputPadding;
z-index: $zindex-form;
transition: width 0.3s;
text-align: left;
box-sizing: border-box;
color: $color-black-0;
background-color: transparent;
}

&__clear {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
right: 0;
z-index: $zindex-form;
height: $height;
width: $inputPadding;
line-height: 0;
vertical-align: middle;
}

&__action {
display: block;
flex: none;
opacity: 0;
height: $height;
line-height: $height;
font-size: $fontSize;
padding-right: $fontSize / 2;
color: $color-brand-dark;
text-align: right;
transition: margin-right 0.3s, opacity 0.3s;
}

&--fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
}
}
63 changes: 63 additions & 0 deletions src/components/search-bar/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Nerv, { findDOMNode } from 'nervjs'
import { renderToString } from 'nerv-server'
import { Simulate, renderIntoDocument } from 'nerv-test-utils'

import AtSearchBar from '../../../.temp/components/search-bar/index'

describe('AtSearchBar Snap', () => {
it('render initial AtSwitch', () => {
const componet = renderToString(<AtSearchBar />)
expect(componet).toMatchSnapshot()
})

it('render AtSearchBar -- props value', () => {
const componet = renderToString(<AtSearchBar value='value' />)
expect(componet).toMatchSnapshot()
})

it('render AtSearchBar -- props placeholder', () => {
const componet = renderToString(<AtSearchBar placeholder='placeholder' />)
expect(componet).toMatchSnapshot()
})

it('render AtSearchBar -- props maxlength', () => {
const componet = renderToString(<AtSearchBar maxlength={120} />)
expect(componet).toMatchSnapshot()
})

it('render AtSearchBar -- props disabled', () => {
const componet1 = renderToString(<AtSearchBar fixed />)
expect(componet1).toMatchSnapshot()
})

it('render AtSearchBar -- props focus', () => {
const componet1 = renderToString(<AtSearchBar focus />)
expect(componet1).toMatchSnapshot()
})

it('render AtSearchBar -- props disabled', () => {
const componet1 = renderToString(<AtSearchBar disabled />)
expect(componet1).toMatchSnapshot()
})

it('render AtSearchBar -- props showActionButton', () => {
const componet1 = renderToString(<AtSearchBar showActionButton />)
expect(componet1).toMatchSnapshot()
})

it('render AtSearchBar -- props actionName', () => {
const componet1 = renderToString(<AtSearchBar actionName='actionName' />)
expect(componet1).toMatchSnapshot()
})
})

describe('AtSearchBar Event', () => {
it('AtSearchBar onChange', () => {
const fn = jest.fn()
const component = renderIntoDocument(<AtSearchBar onChange={fn} />)
const items = findDOMNode(component, 'at-search-bar').querySelectorAll('.at-search-bar__input')
const item0 = items[0]
Simulate.change(item0)
expect(fn).toBeCalled()
})
})
Loading

0 comments on commit 63acb61

Please sign in to comment.