Skip to content

Commit

Permalink
feat(indexes): 新增索引选择器组件
Browse files Browse the repository at this point in the history
  • Loading branch information
jimczj committed Nov 18, 2018
1 parent 56adbc1 commit 995decb
Show file tree
Hide file tree
Showing 11 changed files with 1,661 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class App extends Component {
'pages/navigation/tabbar/index',
'pages/navigation/segmented-control/index',
'pages/navigation/navbar/index',
'pages/navigation/indexes/index',
'pages/layout/flex/index',
'pages/layout/grid/index',
'pages/layout/float-layout/index',
Expand Down
15 changes: 15 additions & 0 deletions src/components/indexes/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AtIndexes Snap render AtIndexes -- props animation 1`] = `"<div class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div></div></div>"`;
exports[`AtIndexes Snap render AtIndexes -- props children 1`] = `"<div class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\">children</div></div></div>"`;
exports[`AtIndexes Snap render AtIndexes -- props className 1`] = `"<div class=\\"at-indexes test\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div></div></div>"`;
exports[`AtIndexes Snap render AtIndexes -- props customStyle 1`] = `"<div style=\\"color:red;\\" class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div></div></div>"`;
exports[`AtIndexes Snap render AtIndexes -- props list 1`] = `"<div class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div><div class=\\"at-indexes__menu-item\\">A</div><div class=\\"at-indexes__menu-item\\">B</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div><div class=\\"at-indexes__list\\"><div id=\\"at-indexes__list-A\\" class=\\"at-indexes__list-title\\">A</div><div class=\\"at-list\\"><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿坝</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿里</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿拉善</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿拉善</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿拉善</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿拉善</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">阿拉善</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div></div></div><div class=\\"at-indexes__list\\"><div id=\\"at-indexes__list-B\\" class=\\"at-indexes__list-title\\">B</div><div class=\\"at-list\\"><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">百度</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">白色</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div><div class=\\"at-list__item\\"><div class=\\"at-list__item-container\\">undefinedundefined<div class=\\"at-list__item-content item-content\\"><div class=\\"item-content__info\\"><div class=\\"item-content__info-title\\">百强</div>undefined</div></div><div class=\\"at-list__item-extra item-extra\\">undefinedundefinedundefinedundefined</div></div></div></div></div></div></div>"`;
exports[`AtIndexes Snap render AtIndexes -- props topKey 1`] = `"<div class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">test</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div></div></div>"`;
exports[`AtIndexes Snap render initial AtIndexes 1`] = `"<div class=\\"at-indexes\\"><div class=\\"at-indexes__menu\\"><div class=\\"at-indexes__menu-item\\">Top</div></div><div scrollY scrollWithAnimation scrollTop=\\"0\\" scrollIntoView=\\"\\" class=\\"taro-scroll taro-scroll-view__scroll-y at-indexes__body\\"><div id=\\"at-indexes__top\\" class=\\"at-indexes__content\\"></div></div></div>"`;
149 changes: 149 additions & 0 deletions src/components/indexes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import Taro from '@tarojs/taro'
import PropTypes from 'prop-types'
import { View, ScrollView } from '@tarojs/components'
import classNames from 'classnames'

import AtComponent from '../../common/component'
import AtList from '../../components/list/index'
import AtListItem from '../../components/list/item/index'

import './index.scss'

export default class AtIndexes extends AtComponent {
static defaultProps = {
customStyle: '',
className: '',
animation: true,
topKey: 'Top',
list: [],
onClick: () => {}
}

static propTypes = {
customStyle: PropTypes.oneOfType([
PropTypes.object,
PropTypes.string
]),
className: PropTypes.oneOfType([
PropTypes.array,
PropTypes.string
]),
animation: PropTypes.bool,
topKey: PropTypes.string,
list: PropTypes.array,
onClick: PropTypes.func
}

constructor () {
super(...arguments)
this.state = {
targetView: '',
targetOffsetTop: 0
}
}

handleClick () {
this.props.onClick(...arguments)
}

jumpTarget (targetView, i) {
const env = Taro.getEnv()
if (env === Taro.ENV_TYPE.WEAPP) {
// 小程序环境
this.setState({
targetView
})
} else if (env === Taro.ENV_TYPE.WEB) {
// web环境
const bodyOffsetTop = this.indexesRef.vnode.dom.offsetTop
// 目标节点offsetTop
const targetOffsetTop = this.listRef.vnode.dom.childNodes[i].offsetTop
this.setState({
targetOffsetTop: targetOffsetTop - bodyOffsetTop
})
}
}

getListRef = node => (this.listRef = node)

getIndexesRef = node => (this.indexesRef = node)

render () {
const {
className,
customStyle,
animation,
topKey,
list
} = this.props
return (
<View
className={
classNames({
'at-indexes': true,
}, className)}
style={customStyle}
ref={this.getIndexesRef}
>
<View className='at-indexes__menu'>
<View
className='at-indexes__menu-item'
onClick={this.jumpTarget.bind(this, 'at-indexes__top', 0)}
>
{topKey}
</View>
{
list.map((item, i) => (
<View
key={item.key}
className='at-indexes__menu-item'
onClick={this.jumpTarget.bind(this, `at-indexes__list-${item.key}`, i + 1)}
>
{item.key}
</View>
))
}
</View>
<ScrollView
className='at-indexes__body'
scrollY
scrollWithAnimation={animation}
scrollTop={this.state.targetOffsetTop}
scrollIntoView={this.state.targetView}
ref={this.getListRef}
>
<View
className='at-indexes__content'
id='at-indexes__top'
>
{this.props.children}
</View>
{
list.map(listItem => (
<View
key={listItem.key}
className='at-indexes__list'
>
<View
id={`at-indexes__list-${listItem.key}`}
className='at-indexes__list-title'
>
{listItem.title}
</View>
<AtList>
{listItem.items && listItem.items.map(item => (
<AtListItem
key={item.name}
title={item.name}
onClick={this.handleClick.bind(this, item)}
/>
))}
</AtList>
</View>
))
}
</ScrollView>
</View>
)
}
}
52 changes: 52 additions & 0 deletions src/components/indexes/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import "../../style/theme/default.scss";
@import "../../style/mixins/index.scss";

.at-indexes {
width: 100%;
height: 100%;
overflow: hidden;
box-sizing: border-box;

&__content {
width: 100%;
overflow: hidden;
box-sizing: border-box;
}

&__menu {
position: fixed;
top: 100px;
right: 10px;
overflow: hidden;
z-index: $zindex-indexes;
}

&__menu-item {
font-size: $font-size-base;
color: $color-link;
padding: 0 $spacing-h-sm;
text-align: center;
}

&__body {
width: 100%;
height: 100%;
box-sizing: border-box;
}

&__list {
width: 100%;
box-sizing: border-box;
overflow: hidden;
}

&__list-title {
font-size: $font-size-lg;
background-color: $color-grey-5;
color: $color-black-2;
padding: $spacing-h-sm $spacing-v-lg;
width: 100%;
box-sizing: border-box;
overflow: hidden;
}
}
85 changes: 85 additions & 0 deletions src/components/indexes/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import Nerv from 'nervjs'
import { renderToString } from 'nerv-server'

import AtIndexes from '../../../.temp/components/indexes/index'

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

it('render AtIndexes -- props className', () => {
const component = renderToString(<AtIndexes className='test' />)
expect(component).toMatchSnapshot()
})

it('render AtIndexes -- props customStyle', () => {
const component = renderToString(<AtIndexes customStyle='color:red;' />)
expect(component).toMatchSnapshot()
})

it('render AtIndexes -- props animation', () => {
const component = renderToString(<AtIndexes animation />)
expect(component).toMatchSnapshot()
})

it('render AtIndexes -- props topKey', () => {
const component = renderToString(<AtIndexes topKey='test' />)
expect(component).toMatchSnapshot()
})

it('render AtIndexes -- props children', () => {
const component = renderToString(<AtIndexes>children</AtIndexes>)
expect(component).toMatchSnapshot()
})

it('render AtIndexes -- props list', () => {
const list = [
{
title: 'A',
key: 'A',
items: [
{
'name': '阿坝',
},
{
'name': '阿里',
},
{
'name': '阿拉善',
},
{
'name': '阿拉善',
},
{
'name': '阿拉善',
},
{
'name': '阿拉善',
},
{
'name': '阿拉善',
}
]
},
{
title: 'B',
key: 'B',
items: [
{
'name': '百度',
},
{
'name': '白色',
},
{
'name': '百强',
}
]
}
]
const component = renderToString(<AtIndexes list={list} />)
expect(component).toMatchSnapshot()
})
})
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export { default as AtSteps } from './components/steps'
export { default as AtCurtain } from './components/curtain'
export { AtMessage, message } from './components/message'
export { default as AtImagePicker } from './components/image-picker'
export { default as AtIndexes } from './components/indexes'

/* 私有的组件 */
export { default as AtLoading } from './components/loading'
Expand Down
43 changes: 43 additions & 0 deletions src/pages/navigation/indexes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import AtIndexes from '../../../components/indexes/index'
import DocsHeader from '../../components/doc-header'
import mockData from './mock-data'
import './index.scss'

export default class Index extends Taro.Component {
config = {
navigationBarTitleText: 'Taro UI'
}
onClick (item) {
console.log(item)
}

render () {
return (
<View className='page' style='height: 100vh;'>
{/* S Header */}
<DocsHeader title='Indexes 索引选择器'></DocsHeader>
{/* E Header */}
{/* S Body */}
<View className='doc-body' style='height: 100%;'>
{/* 基础用法 */}
<View className='panel' style='height: 100%;'>
<View className='panel__title'>基础用法</View>
<AtIndexes
list={mockData}
topKey='Top'
onClick={this.onClick.bind(this)}
>
<View style='padding:20px;text-align:center;font-size: 18px;'>
用户自定义内容
</View>
</AtIndexes>
</View>
</View>

{/* E Body */}
</View>
)
}
}
4 changes: 4 additions & 0 deletions src/pages/navigation/indexes/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.example-item {
color: #333;
font-size: 28px;
}
Loading

0 comments on commit 995decb

Please sign in to comment.