-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c77e261
commit 9af9f79
Showing
13 changed files
with
532 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { PureComponent } from "react"; | ||
import PropTypes from "prop-types"; | ||
import cls from "classnames"; | ||
import CityPickerCore from "./CityPickerCore"; | ||
import Input from "../input"; | ||
import { DownIcon } from "../icon"; | ||
|
||
export default class CityPicker extends PureComponent { | ||
state = { | ||
visible: false | ||
}; | ||
static defaultProps = { | ||
prefixCls: "cuke-city-picker", | ||
cityList: [], | ||
disabled: false, | ||
placeholder: "请选择" | ||
}; | ||
static propTypes = { | ||
cityList: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
group: PropTypes.string.isRequired, | ||
resources: PropTypes.arrayOf(PropTypes.object) | ||
}) | ||
).isRequired, | ||
disabled: PropTypes.bool, | ||
placeholder: PropTypes.string, | ||
onCityGroupChange: PropTypes.func, | ||
onCityChange: PropTypes.func | ||
}; | ||
state = { | ||
selectedCityGroup: "热门", | ||
selectedCityName: "" | ||
}; | ||
|
||
onCityGroupChange = selectedCityGroup => { | ||
if (this.props.onCityGroupChange) { | ||
this.props.onCityGroupChange(selectedCityGroup); | ||
} | ||
}; | ||
onCityChange = selectedCity => { | ||
this.setState({ visible: false, selectedCityName: selectedCity.name }); | ||
|
||
if (this.props.onCityChange) { | ||
this.props.onCityChange(selectedCity); | ||
} | ||
}; | ||
|
||
onOpenCityPicker = () => { | ||
this.setState({ visible: true }); | ||
}; | ||
|
||
onCloseCityPicker = () => { | ||
// this.setState({visible: false}) | ||
}; | ||
render() { | ||
const { | ||
cityList, | ||
prefixCls, | ||
disabled, | ||
placeholder, | ||
className, | ||
...attr | ||
} = this.props; | ||
const { visible, selectedCityName } = this.state; | ||
return ( | ||
<div className={cls(`${prefixCls}`, className)} {...attr}> | ||
<div className={cls(`${prefixCls}-inner`)}> | ||
<Input | ||
disabled={disabled} | ||
readonly | ||
placeholder={placeholder} | ||
className={cls(`${prefixCls}-input`)} | ||
onFocus={this.onOpenCityPicker} | ||
onBlur={this.onCloseCityPicker} | ||
value={selectedCityName} | ||
/> | ||
<DownIcon className={`${prefixCls}-arrow`} /> | ||
</div> | ||
<div | ||
className={cls(`${prefixCls}-content`, { | ||
[`${prefixCls}-open`]: visible, | ||
[`${prefixCls}-close`]: !visible | ||
})} | ||
> | ||
<CityPickerCore | ||
cityList={cityList} | ||
onCityChange={this.onCityChange} | ||
onCityGroupChange={this.onCityGroupChange} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { PureComponent } from "react"; | ||
import PropTypes from "prop-types"; | ||
import cls from "classnames"; | ||
|
||
export default class CityPickerCore extends PureComponent { | ||
static defaultProps = { | ||
prefixCls: "cuke-city-picker-core", | ||
cityList: [] | ||
}; | ||
static propTypes = { | ||
cityList: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
group: PropTypes.string.isRequired, | ||
resources: PropTypes.arrayOf(PropTypes.object) | ||
}) | ||
).isRequired, | ||
onCityGroupChange: PropTypes.func, | ||
onCityChange: PropTypes.func | ||
}; | ||
state = { | ||
selectedCityGroup: "热门", | ||
selectedCityName: "" | ||
}; | ||
|
||
onCityGroupChange = selectedCityGroup => () => { | ||
this.setState({ selectedCityGroup }); | ||
|
||
if (this.props.onCityGroupChange) { | ||
this.props.onCityGroupChange(selectedCityGroup); | ||
} | ||
}; | ||
onCityChange = selectedCity => () => { | ||
this.setState({ selectedCityName: selectedCity.name }); | ||
if (this.props.onCityChange) { | ||
this.props.onCityChange(selectedCity); | ||
} | ||
}; | ||
|
||
render() { | ||
const { | ||
cityList, | ||
prefixCls, | ||
className, | ||
onCityGroupChange, //eslint-disable-line | ||
onCityChange, //eslint-disable-line | ||
...attr | ||
} = this.props; | ||
const { selectedCityGroup, selectedCityName } = this.state; | ||
const cityGroups = | ||
cityList.length >= 1 ? cityList.map(({ group }) => group) : []; | ||
|
||
return ( | ||
<div className={cls(`${prefixCls}`, className)} {...attr}> | ||
<div className={cls(`${prefixCls}-panel`)}> | ||
<div className={cls(`${prefixCls}-panel-header`)}> | ||
<ul className={cls(`${prefixCls}-panel-header-wrap`)}> | ||
{cityGroups.map((cityGroup, i) => { | ||
return ( | ||
<li | ||
onClick={this.onCityGroupChange(cityGroup)} | ||
className={cls("item", { | ||
active: selectedCityGroup === cityGroup | ||
})} | ||
key={i} | ||
> | ||
<span>{cityGroup}</span> | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
</div> | ||
<div className={cls(`${prefixCls}-panel-content`)}> | ||
<ul className={cls(`${prefixCls}-panel-content-wrap`)}> | ||
{cityList.length >= 1 && | ||
cityList | ||
.find(item => item.group === selectedCityGroup) | ||
.resources.map((city, i) => { | ||
return ( | ||
<li | ||
className={cls("city", { | ||
selected: selectedCityName === city.name | ||
})} | ||
key={i} | ||
onClick={this.onCityChange(city)} | ||
> | ||
{city.name} | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
components/cityPicker/__tests__/__snapshots__/index.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`<CityPicker/> should render CityPicker 1`] = ` | ||
<div | ||
class="cuke-city-picker" | ||
> | ||
<div | ||
class="cuke-city-picker-inner" | ||
> | ||
<input | ||
class="cuke-input cuke-city-picker-input" | ||
placeholder="请选择" | ||
readonly="" | ||
type="text" | ||
value="" | ||
/> | ||
<svg | ||
attr="[object Object]" | ||
class="undefined cuke-city-picker-arrow" | ||
fill="none" | ||
height="1em" | ||
stroke="currentColor" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
stroke-width="2" | ||
viewBox="0 0 24 24" | ||
width="1em" | ||
> | ||
<polyline | ||
points="6 9 12 15 18 9" | ||
/> | ||
</svg> | ||
</div> | ||
<div | ||
class="cuke-city-picker-content cuke-city-picker-close" | ||
> | ||
<div | ||
class="cuke-city-picker-core" | ||
> | ||
<div | ||
class="cuke-city-picker-core-panel" | ||
> | ||
<div | ||
class="cuke-city-picker-core-panel-header" | ||
> | ||
<ul | ||
class="cuke-city-picker-core-panel-header-wrap" | ||
/> | ||
</div> | ||
<div | ||
class="cuke-city-picker-core-panel-content" | ||
> | ||
<ul | ||
class="cuke-city-picker-core-panel-content-wrap" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import assert from "power-assert"; | ||
import React from "react"; | ||
import { render, shallow } from "enzyme"; | ||
import toJson from "enzyme-to-json"; | ||
import CityPicker from "../index"; | ||
import Input from "../../input"; | ||
import CityPickerCore from "../CityPickerCore"; | ||
|
||
describe("<CityPicker/>", () => { | ||
it("should render CityPicker", () => { | ||
const wrapper = render(<CityPicker />); | ||
expect(toJson(wrapper)).toMatchSnapshot(); | ||
}); | ||
|
||
it("should render Input when render CityPicker", () => { | ||
const wrapper = shallow(<CityPicker />); | ||
assert(wrapper.find(Input).length === 1); | ||
}); | ||
|
||
it("should render CityPickerCore when render CityPicker", () => { | ||
const wrapper = shallow(<CityPicker />); | ||
assert(wrapper.find(CityPickerCore).length === 1); | ||
}); | ||
|
||
it("should render cuke-city-picker classnames", () => { | ||
const wrapper = shallow(<CityPicker />); | ||
assert(wrapper.find(".cuke-city-picker").length === 1); | ||
}); | ||
|
||
it("should render cuke-city-picker-core classnames", () => { | ||
const wrapper = shallow(<CityPickerCore />); | ||
assert(wrapper.find(".cuke-city-picker-core").length === 1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,6 @@ | ||
import React, { PureComponent } from "react"; | ||
import cls from "classnames"; | ||
import CityPickerCore from "./CityPickerCore"; | ||
import CityPicker from "./CityPicker"; | ||
|
||
export default class CityPicker extends PureComponent { | ||
static defaultProps = { | ||
prefixCls: "cuke-city-picker", | ||
cityList: [] | ||
}; | ||
state = { | ||
selectedCityGroup: "热门", | ||
selectedCityName: "" | ||
}; | ||
CityPicker.CityPickerCore = CityPickerCore; | ||
|
||
onCityGroupChange = selectedCityGroup => () => { | ||
this.setState({ selectedCityGroup }); | ||
|
||
if (this.props.onCityGroupChange) { | ||
this.props.onCityGroupChange(selectedCityGroup); | ||
} | ||
}; | ||
onCityChange = selectedCity => () => { | ||
this.setState({ selectedCityName: selectedCity.name }); | ||
if (this.props.onCityChange) { | ||
this.props.onCityChange(selectedCity); | ||
} | ||
}; | ||
|
||
render() { | ||
const { cityList, prefixCls } = this.props; | ||
const { selectedCityGroup, selectedCityName } = this.state; | ||
const cityGroups = | ||
cityList.length >= 1 ? cityList.map(({ group }) => group) : []; | ||
|
||
return ( | ||
<div className={`${prefixCls}`}> | ||
<div className={cls(`${prefixCls}-panel`)}> | ||
<div className={cls(`${prefixCls}-panel-header`)}> | ||
<ul className={cls(`${prefixCls}-panel-header-wrap`)}> | ||
{cityGroups.map((cityGroup, i) => { | ||
return ( | ||
<li | ||
onClick={this.onCityGroupChange(cityGroup)} | ||
className={cls("item", { | ||
active: selectedCityGroup === cityGroup | ||
})} | ||
key={i} | ||
> | ||
<span>{cityGroup}</span> | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
</div> | ||
<div className={cls(`${prefixCls}-panel-content`)}> | ||
<ul className={cls(`${prefixCls}-panel-content-wrap`)}> | ||
{cityList.length >= 1 && | ||
cityList | ||
.find(item => item.group === selectedCityGroup) | ||
.resources.map((city, i) => { | ||
return ( | ||
<li | ||
className={cls("city", { | ||
selected: selectedCityName === city.name | ||
})} | ||
key={i} | ||
onClick={this.onCityChange(city)} | ||
> | ||
{city.name} | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
export default CityPicker; |
Oops, something went wrong.