diff options
Diffstat (limited to 'src/TimePicker.jsx')
-rw-r--r-- | src/TimePicker.jsx | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/TimePicker.jsx b/src/TimePicker.jsx new file mode 100644 index 0000000..6bb97a1 --- /dev/null +++ b/src/TimePicker.jsx | |||
@@ -0,0 +1,140 @@ | |||
1 | import React, {PropTypes} from 'react'; | ||
2 | import ReactDOM from 'react-dom'; | ||
3 | import Trigger from 'rc-trigger'; | ||
4 | import {createChainedFunction} from 'rc-util'; | ||
5 | import placements from './util/placements'; | ||
6 | import CommonMixin from './mixin/CommonMixin'; | ||
7 | |||
8 | function noop() { | ||
9 | } | ||
10 | |||
11 | function refFn(field, component) { | ||
12 | this[field] = component; | ||
13 | } | ||
14 | |||
15 | const Picker = React.createClass({ | ||
16 | propTypes: { | ||
17 | prefixCls: PropTypes.string, | ||
18 | panel: PropTypes.element, | ||
19 | children: PropTypes.func, | ||
20 | disabled: PropTypes.bool, | ||
21 | value: PropTypes.object, | ||
22 | open: PropTypes.bool, | ||
23 | align: PropTypes.object, | ||
24 | placement: PropTypes.any, | ||
25 | transitionName: PropTypes.string, | ||
26 | onChange: PropTypes.func, | ||
27 | onOpen: PropTypes.func, | ||
28 | onClose: PropTypes.func, | ||
29 | }, | ||
30 | |||
31 | mixins: [CommonMixin], | ||
32 | |||
33 | getDefaultProps() { | ||
34 | return { | ||
35 | open: false, | ||
36 | align: {}, | ||
37 | placement: 'bottomLeft', | ||
38 | onChange: noop, | ||
39 | onOpen: noop, | ||
40 | onClose: noop, | ||
41 | }; | ||
42 | }, | ||
43 | |||
44 | getInitialState() { | ||
45 | this.savePanelRef = refFn.bind(this, 'panelInstance'); | ||
46 | const { open, value } = this.props; | ||
47 | return { open, value }; | ||
48 | }, | ||
49 | |||
50 | componentWillReceiveProps(nextProps) { | ||
51 | const { value, open } = nextProps; | ||
52 | if (value !== undefined) { | ||
53 | this.setState({value}); | ||
54 | } | ||
55 | if (open !== undefined) { | ||
56 | this.setState({open}); | ||
57 | } | ||
58 | }, | ||
59 | |||
60 | onPanelChange(value) { | ||
61 | const props = this.props; | ||
62 | this.setState({ | ||
63 | value: value, | ||
64 | }); | ||
65 | props.onChange(value); | ||
66 | }, | ||
67 | |||
68 | onPanelClear() { | ||
69 | this.setOpen(false, this.focus); | ||
70 | }, | ||
71 | |||
72 | onVisibleChange(open) { | ||
73 | this.setOpen(open, () => { | ||
74 | if (open) { | ||
75 | ReactDOM.findDOMNode(this.panelInstance).focus(); | ||
76 | } | ||
77 | }); | ||
78 | }, | ||
79 | |||
80 | getPanelElement() { | ||
81 | const panel = this.props.panel; | ||
82 | const extraProps = { | ||
83 | ref: this.savePanelRef, | ||
84 | defaultValue: this.state.value || panel.props.defaultValue, | ||
85 | onChange: createChainedFunction(panel.props.onChange, this.onPanelChange), | ||
86 | onClear: createChainedFunction(panel.props.onClear, this.onPanelClear), | ||
87 | }; | ||
88 | |||
89 | return React.cloneElement(panel, extraProps); | ||
90 | }, | ||
91 | |||
92 | setOpen(open, callback) { | ||
93 | const {onOpen, onClose} = this.props; | ||
94 | if (this.state.open !== open) { | ||
95 | this.setState({ | ||
96 | open: open, | ||
97 | }, callback); | ||
98 | const event = { | ||
99 | open: open, | ||
100 | }; | ||
101 | if (open) { | ||
102 | onOpen(event); | ||
103 | } else { | ||
104 | onClose(event); | ||
105 | } | ||
106 | } | ||
107 | }, | ||
108 | |||
109 | focus() { | ||
110 | if (!this.state.open) { | ||
111 | ReactDOM.findDOMNode(this).focus(); | ||
112 | } | ||
113 | }, | ||
114 | |||
115 | render() { | ||
116 | const state = this.state; | ||
117 | const props = this.props; | ||
118 | const { prefixCls, placement, align, disabled, transitionName, children } = props; | ||
119 | return ( | ||
120 | <Trigger | ||
121 | prefixCls={prefixCls} | ||
122 | popup={this.getPanelElement()} | ||
123 | popupAlign={align} | ||
124 | builtinPlacements={placements} | ||
125 | popupPlacement={placement} | ||
126 | action={disabled ? [] : ['click']} | ||
127 | destroyPopupOnHide | ||
128 | popupTransitionName={transitionName} | ||
129 | popupVisible={state.open} | ||
130 | onPopupVisibleChange={this.onVisibleChange} | ||
131 | > | ||
132 | <span className={`${prefixCls}-picker`}> | ||
133 | {children(state, props)} | ||
134 | </span> | ||
135 | </Trigger> | ||
136 | ); | ||
137 | }, | ||
138 | }); | ||
139 | |||
140 | export default Picker; | ||