@seafile/seafile-calendar 0.1.2-beta.0 → 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,103 +36,232 @@ var CalendarRightPanel = function (_React$Component) {
36
36
 
37
37
  var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this, props));
38
38
 
39
- _this.onSelect = function (value) {
40
- _this.setState({
41
- highlightTime: value
42
- });
43
- _this.props.onSelect(value);
44
- _this.props.onClickRightPanelTime();
39
+ _this.centerScroll = function (container, index) {
40
+ if (!container || index < 0) return;
41
+ var firstItem = container.querySelector('li');
42
+ var itemHeight = firstItem && firstItem.offsetHeight || 32;
43
+ var containerHeight = container.clientHeight || 0;
44
+ var maxScroll = Math.max(0, container.scrollHeight - containerHeight);
45
+ var target = index * itemHeight - (containerHeight / 2 - itemHeight / 2);
46
+ if (target < 0) target = 0;
47
+ if (target > maxScroll) target = maxScroll;
48
+ container.scrollTop = target;
45
49
  };
46
50
 
47
- _this.getTimes = function () {
48
- var times = [];
49
- for (var i = 0; i < 24; i++) {
50
- var str = (String(i) + ':00').padStart(5, '0');
51
- var str1 = (String(i) + ':30').padStart(5, '0');
52
- times.push(str);
53
- times.push(str1);
51
+ _this.onSelectMinute = function (minute) {
52
+ var base = _this.props.selectedValue || _this.props.value || _this.state.highlightTime || (0, _dayjs2['default'])();
53
+ var h = parseInt(_this.getSelectedHour(), 10) || 0;
54
+ var m = parseInt(minute, 10) || 0;
55
+ var current = base.clone().hour(h).minute(m);
56
+ _this.skipScrollUpdates = 2;
57
+ _this.setState({ highlightTime: current });
58
+ _this.props.onSelect(current);
59
+ if (_this.props.onClickRightPanelTime) {
60
+ _this.props.onClickRightPanelTime();
54
61
  }
55
- return times;
56
62
  };
57
63
 
58
- _this.scrollUp = function () {
59
- _this.timeRef.current.scrollBy(0, -200);
64
+ _this.onSelectHour = function (hour) {
65
+ var base = _this.props.selectedValue || _this.props.value || _this.state.highlightTime || (0, _dayjs2['default'])();
66
+ var h = parseInt(hour, 10) || 0;
67
+ var m = parseInt(_this.getSelectedMinute(), 10) || 0;
68
+ var current = base.clone().hour(h).minute(m);
69
+ _this.skipScrollUpdates = 2;
70
+ _this.setState({ highlightTime: current });
71
+ _this.props.onSelect(current);
72
+ };
73
+
74
+ _this.getHours = function () {
75
+ return Array.from({ length: 24 }, function (_, i) {
76
+ return String(i).padStart(2, '0');
77
+ });
78
+ };
79
+
80
+ _this.getMinutes = function () {
81
+ return Array.from({ length: 60 }, function (_, i) {
82
+ return String(i).padStart(2, '0');
83
+ });
60
84
  };
61
85
 
62
- _this.scrollDown = function () {
63
- _this.timeRef.current.scrollBy(0, 200);
86
+ _this.getSelectedHour = function () {
87
+ var highlightTime = _this.state.highlightTime;
88
+ var _this$props = _this.props,
89
+ value = _this$props.value,
90
+ selectedValue = _this$props.selectedValue;
91
+
92
+ var v = highlightTime || selectedValue || value;
93
+ return v ? v.format('HH') : '00';
94
+ };
95
+
96
+ _this.getSelectedMinute = function () {
97
+ var highlightTime = _this.state.highlightTime;
98
+ var _this$props2 = _this.props,
99
+ value = _this$props2.value,
100
+ selectedValue = _this$props2.selectedValue;
101
+
102
+ var v = highlightTime || selectedValue || value;
103
+ return v ? v.format('mm') : '00';
64
104
  };
65
105
 
66
106
  var format = Array.isArray(_this.props.format) ? _this.props.format[0] : _this.props.format;
67
107
  _this.state = {
68
- highlightTime: _this.props.value || null,
108
+ highlightTime: _this.props.selectedValue || _this.props.value || null,
69
109
  localeFormat: format
70
110
  };
71
- _this.timeRef = _react2['default'].createRef();
72
- _this.times = _this.getTimes();
111
+
112
+ _this.hoursRef = _react2['default'].createRef();
113
+ _this.minutesRef = _react2['default'].createRef();
114
+ _this.hours = _this.getHours();
115
+ _this.minutes = _this.getMinutes();
116
+
117
+ _this.skipScrollUpdates = 0;
73
118
  return _this;
74
119
  }
75
120
 
121
+ CalendarRightPanel.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
122
+ if (nextProps.selectedValue) {
123
+ if (!prevState.highlightTime || !prevState.highlightTime.isSame(nextProps.selectedValue)) {
124
+ return { highlightTime: nextProps.selectedValue };
125
+ }
126
+ }
127
+ return null;
128
+ };
129
+
76
130
  CalendarRightPanel.prototype.componentDidMount = function componentDidMount() {
77
- var defaultMinutesTime = this.props.defaultMinutesTime;
131
+ var _this2 = this;
78
132
 
79
- var showTimeIndex = this.times.findIndex(function (item) {
80
- return item >= defaultMinutesTime;
133
+ var _props = this.props,
134
+ defaultMinutesTime = _props.defaultMinutesTime,
135
+ value = _props.value,
136
+ selectedValue = _props.selectedValue;
137
+
138
+ var baseTime = defaultMinutesTime || (selectedValue || value ? (selectedValue || value).format('HH:mm') : '00:00');
139
+ var base = baseTime.split(':');
140
+ var hIdx = this.hours.findIndex(function (h) {
141
+ return h === base[0];
142
+ });
143
+ var mIdx = this.minutes.findIndex(function (m) {
144
+ return m === base[1];
81
145
  });
82
- var scrollTimeIndex = showTimeIndex > -1 ? showTimeIndex - 1 : 16;
83
- this.timeRef.current.scrollTo(0, 34 * scrollTimeIndex);
146
+ var hourIndex = hIdx > -1 ? hIdx : 0;
147
+ var minuteIndex = mIdx > -1 ? mIdx : 0;
148
+
149
+ if (typeof window !== 'undefined' && window.requestAnimationFrame) {
150
+ window.requestAnimationFrame(function () {
151
+ _this2.centerScroll(_this2.hoursRef.current, hourIndex);
152
+ _this2.centerScroll(_this2.minutesRef.current, minuteIndex);
153
+ });
154
+ } else {
155
+ this.centerScroll(this.hoursRef.current, hourIndex);
156
+ this.centerScroll(this.minutesRef.current, minuteIndex);
157
+ }
158
+ };
159
+
160
+ CalendarRightPanel.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
161
+ var _this3 = this;
162
+
163
+ var prevV = prevState.highlightTime || prevProps.selectedValue || prevProps.value;
164
+ var currV = this.state.highlightTime || this.props.selectedValue || this.props.value;
165
+
166
+ var prevH = prevV ? prevV.format('HH') : '00';
167
+ var prevM = prevV ? prevV.format('mm') : '00';
168
+ var currH = currV ? currV.format('HH') : '00';
169
+ var currM = currV ? currV.format('mm') : '00';
170
+
171
+ if (this.skipScrollUpdates > 0) {
172
+ this.skipScrollUpdates -= 1;
173
+ return;
174
+ }
175
+
176
+ var hChanged = prevH !== currH;
177
+ var mChanged = prevM !== currM;
178
+ if (hChanged || mChanged) {
179
+ var scrollHours = function scrollHours() {
180
+ if (hChanged) {
181
+ var hIdx = _this3.hours.findIndex(function (h) {
182
+ return h === currH;
183
+ });
184
+ var hourIndex = hIdx > -1 ? hIdx : 0;
185
+ _this3.centerScroll(_this3.hoursRef.current, hourIndex);
186
+ }
187
+ if (mChanged) {
188
+ var mIdx = _this3.minutes.findIndex(function (m) {
189
+ return m === currM;
190
+ });
191
+ var minuteIndex = mIdx > -1 ? mIdx : 0;
192
+ _this3.centerScroll(_this3.minutesRef.current, minuteIndex);
193
+ }
194
+ };
195
+ if (typeof window !== 'undefined' && window.requestAnimationFrame) {
196
+ window.requestAnimationFrame(scrollHours);
197
+ } else {
198
+ scrollHours();
199
+ }
200
+ }
84
201
  };
85
202
 
86
203
  CalendarRightPanel.prototype.render = function render() {
87
- var _this2 = this;
204
+ var _this4 = this;
88
205
 
89
- var _props = this.props,
90
- value = _props.value,
91
- prefixCls = _props.prefixCls,
92
- locale = _props.locale;
206
+ var prefixCls = this.props.prefixCls;
93
207
 
94
- var highlight = this.state.highlightTime;
95
- var highlightTime = highlight ? highlight.format().slice(11, 16) : null;
96
- var isZhcn = locale && locale.today === '今天';
208
+ var selectedHour = this.getSelectedHour();
209
+ var selectedMinute = this.getSelectedMinute();
97
210
  return _react2['default'].createElement(
98
211
  'div',
99
212
  { className: prefixCls + '-right-panel' },
100
213
  _react2['default'].createElement(
101
214
  'div',
102
- { className: prefixCls + '-right-panel-header', onClick: this.scrollUp },
103
- _react2['default'].createElement('span', null)
215
+ { className: prefixCls + '-right-panel-time-header' },
216
+ selectedHour,
217
+ ':',
218
+ selectedMinute
104
219
  ),
105
220
  _react2['default'].createElement(
106
221
  'div',
107
- { className: prefixCls + '-right-panel-body', ref: this.timeRef },
222
+ { className: prefixCls + '-right-panel-body' },
108
223
  _react2['default'].createElement(
109
- 'ul',
110
- null,
111
- this.times.map(function (time) {
112
- var _time$split$map = time.split(':').map(function (n) {
113
- return parseInt(n, 10);
114
- }),
115
- h = _time$split$map[0],
116
- m = _time$split$map[1];
117
-
118
- var current = value.hour(h).minute(m).second(0);
119
- current = isZhcn ? current.locale('zh-cn') : current.locale('en-gb');
120
- return _react2['default'].createElement(
121
- 'li',
122
- {
123
- key: time,
124
- onClick: _this2.onSelect.bind(_this2, current),
125
- className: '' + (highlightTime === time ? prefixCls + '-selected-time' : '')
126
- },
127
- time
128
- );
129
- })
224
+ 'div',
225
+ { className: prefixCls + '-right-panel-col', ref: this.hoursRef },
226
+ _react2['default'].createElement(
227
+ 'ul',
228
+ null,
229
+ this.hours.map(function (h) {
230
+ return _react2['default'].createElement(
231
+ 'li',
232
+ {
233
+ key: h,
234
+ onClick: function onClick() {
235
+ return _this4.onSelectHour(h);
236
+ },
237
+ className: prefixCls + '-right-panel-item ' + (h === selectedHour ? prefixCls + '-right-panel-item-selected' : '')
238
+ },
239
+ h
240
+ );
241
+ })
242
+ )
243
+ ),
244
+ _react2['default'].createElement(
245
+ 'div',
246
+ { className: prefixCls + '-right-panel-col', ref: this.minutesRef },
247
+ _react2['default'].createElement(
248
+ 'ul',
249
+ null,
250
+ this.minutes.map(function (m) {
251
+ return _react2['default'].createElement(
252
+ 'li',
253
+ {
254
+ key: m,
255
+ onClick: function onClick() {
256
+ return _this4.onSelectMinute(m);
257
+ },
258
+ className: prefixCls + '-right-panel-item ' + (m === selectedMinute ? prefixCls + '-right-panel-item-selected' : '')
259
+ },
260
+ m
261
+ );
262
+ })
263
+ )
130
264
  )
131
- ),
132
- _react2['default'].createElement(
133
- 'div',
134
- { className: prefixCls + '-right-panel-footer', onClick: this.scrollDown },
135
- _react2['default'].createElement('span', null)
136
265
  )
137
266
  );
138
267
  };
@@ -143,6 +272,7 @@ var CalendarRightPanel = function (_React$Component) {
143
272
  CalendarRightPanel.propTypes = {
144
273
  prefixCls: _propTypes2['default'].string,
145
274
  value: _propTypes2['default'].object,
275
+ selectedValue: _propTypes2['default'].object,
146
276
  onSelect: _propTypes2['default'].func,
147
277
  onClickRightPanelTime: _propTypes2['default'].func,
148
278
  locale: _propTypes2['default'].object,
@@ -181,7 +181,6 @@ var _initialiseProps = function _initialiseProps() {
181
181
  onChange = _props.onChange,
182
182
  selectedValue = _props.selectedValue;
183
183
 
184
- // 没有内容,合法并直接退出
185
184
 
186
185
  if (!str || !calendarStr) {
187
186
  _this3.setState({ isInputEmpty: true });
@@ -0,0 +1,234 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+
5
+ var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
6
+
7
+ var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
8
+
9
+ var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
10
+
11
+ var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
12
+
13
+ var _inherits2 = require('babel-runtime/helpers/inherits');
14
+
15
+ var _inherits3 = _interopRequireDefault(_inherits2);
16
+
17
+ var _react = require('react');
18
+
19
+ var _react2 = _interopRequireDefault(_react);
20
+
21
+ var _reactDom = require('react-dom');
22
+
23
+ var _reactDom2 = _interopRequireDefault(_reactDom);
24
+
25
+ var _propTypes = require('prop-types');
26
+
27
+ var _propTypes2 = _interopRequireDefault(_propTypes);
28
+
29
+ var _reactLifecyclesCompat = require('react-lifecycles-compat');
30
+
31
+ var _dayjs = require('dayjs');
32
+
33
+ var _dayjs2 = _interopRequireDefault(_dayjs);
34
+
35
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
36
+
37
+ var customParseFormat = require('dayjs/plugin/customParseFormat');
38
+ _dayjs2['default'].extend(customParseFormat);
39
+
40
+ function formatTime(value, format) {
41
+ if (!value) return '';
42
+ var fmt = Array.isArray(format) ? format[0] : format || 'HH:mm';
43
+ return value.format(fmt);
44
+ }
45
+
46
+ // Convert a loose numeric/time string into HH:mm
47
+ // Rules (similar spirit to DateInput.initializeStr):
48
+ // - Strip non-digits
49
+ // - If len <= 2 => treat as hour
50
+ // - If len > 2 => last two digits are minutes; preceding are hours
51
+ // - Clamp hours to [0,23], minutes to [0,59]
52
+ // - Return formatted HH:mm or '' when input is empty
53
+ function initializeTime(str) {
54
+ if (typeof str !== 'string') return '';
55
+ var digits = str.replace(/\D/g, '');
56
+ if (!digits.length) return '';
57
+
58
+ var hDigits = '';
59
+ var mDigits = '';
60
+ if (digits.length <= 2) {
61
+ hDigits = digits;
62
+ } else {
63
+ hDigits = digits.slice(0, digits.length - 2);
64
+ mDigits = digits.slice(-2);
65
+ }
66
+
67
+ var hour = parseInt(hDigits || '0', 10);
68
+ var minute = parseInt(mDigits || '0', 10);
69
+ if (Number.isNaN(hour)) hour = 0;
70
+ if (Number.isNaN(minute)) minute = 0;
71
+
72
+ if (hour > 23) hour = 23;
73
+ if (minute > 59) minute = 59;
74
+
75
+ var HH = String(hour).padStart(2, '0');
76
+ var mm = String(minute).padStart(2, '0');
77
+ return HH + ':' + mm;
78
+ }
79
+
80
+ var timeInputInstance = void 0;
81
+ var cachedSelectionStart = void 0;
82
+ var cachedSelectionEnd = void 0;
83
+
84
+ var TimeInput = function (_React$Component) {
85
+ (0, _inherits3['default'])(TimeInput, _React$Component);
86
+
87
+ function TimeInput(props) {
88
+ (0, _classCallCheck3['default'])(this, TimeInput);
89
+
90
+ var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this, props));
91
+
92
+ _this.onInputChange = function (event) {
93
+ var str = event.target.value;
94
+ var timeStr = initializeTime(str);
95
+
96
+ if (!str || !timeStr) {
97
+ _this.setState({ str: str, isInputEmpty: true });
98
+ return;
99
+ }
100
+
101
+ if (_this.state.isInputEmpty) {
102
+ _this.setState({ isInputEmpty: false });
103
+ }
104
+
105
+ var base = _this.props.selectedValue || _this.props.value || (0, _dayjs2['default'])();
106
+ var parsed = (0, _dayjs2['default'])(timeStr, 'HH:mm');
107
+ var next = base.clone().hour(parsed.hour()).minute(parsed.minute());
108
+
109
+ _this.setState({ str: str });
110
+ if (_this.props.onChange) {
111
+ _this.props.onChange(next);
112
+ }
113
+ };
114
+
115
+ _this.onKeyDown = function (event) {
116
+ if (event.key === 'Enter' && _this.props.onSelect) {
117
+ var timeStr = initializeTime(_this.state.str);
118
+ if (!timeStr) return;
119
+ var base = _this.props.selectedValue || _this.props.value || (0, _dayjs2['default'])();
120
+ var parsed = (0, _dayjs2['default'])(timeStr, 'HH:mm');
121
+ var next = base.clone().hour(parsed.hour()).minute(parsed.minute());
122
+ _this.props.onSelect(next);
123
+ event.preventDefault();
124
+ }
125
+ };
126
+
127
+ _this.onFocus = function () {
128
+ _this.setState({ hasFocus: true });
129
+ };
130
+
131
+ _this.onBlur = function () {
132
+ var base = _this.props.showFromSelected ? _this.props.selectedValue || null : null;
133
+ _this.setState({
134
+ hasFocus: false,
135
+ str: base ? formatTime(base, _this.props.format) : ''
136
+ });
137
+ };
138
+
139
+ _this.saveRef = function (node) {
140
+ timeInputInstance = node;
141
+ };
142
+
143
+ _this.getRootDOMNode = function () {
144
+ return _reactDom2['default'].findDOMNode(_this);
145
+ };
146
+
147
+ _this.state = {
148
+ str: '',
149
+ hasFocus: false,
150
+ isInputEmpty: true
151
+ };
152
+ return _this;
153
+ }
154
+
155
+ TimeInput.prototype.componentDidUpdate = function componentDidUpdate() {
156
+ if (timeInputInstance && this.state.hasFocus && !(cachedSelectionStart === 0 && cachedSelectionEnd === 0)) {
157
+ timeInputInstance.setSelectionRange(cachedSelectionStart, cachedSelectionEnd);
158
+ }
159
+ };
160
+
161
+ TimeInput.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, state) {
162
+ var newState = null;
163
+ if (timeInputInstance) {
164
+ cachedSelectionStart = timeInputInstance.selectionStart;
165
+ cachedSelectionEnd = timeInputInstance.selectionEnd;
166
+ }
167
+
168
+ if (!state.hasFocus) {
169
+ if (nextProps.showFromSelected && nextProps.selectedValue) {
170
+ newState = { str: formatTime(nextProps.selectedValue, nextProps.format) };
171
+ } else {
172
+ newState = { str: '' };
173
+ }
174
+ }
175
+ return newState;
176
+ };
177
+
178
+ TimeInput.getInstance = function getInstance() {
179
+ return timeInputInstance;
180
+ };
181
+
182
+ TimeInput.prototype.render = function render() {
183
+ var _props = this.props,
184
+ prefixCls = _props.prefixCls,
185
+ placeholder = _props.placeholder,
186
+ inputMode = _props.inputMode,
187
+ disabled = _props.disabled,
188
+ className = _props.className;
189
+
190
+ var inputCls = className || prefixCls + '-time-input ' + prefixCls + '-text-input';
191
+ return _react2['default'].createElement(
192
+ 'div',
193
+ { className: prefixCls + '-time-input-outer' },
194
+ _react2['default'].createElement('input', {
195
+ ref: this.saveRef,
196
+ className: inputCls,
197
+ value: this.state.str,
198
+ disabled: disabled,
199
+ placeholder: placeholder,
200
+ onChange: this.onInputChange,
201
+ onKeyDown: this.onKeyDown,
202
+ onFocus: this.onFocus,
203
+ onBlur: this.onBlur,
204
+ inputMode: inputMode
205
+ })
206
+ );
207
+ };
208
+
209
+ return TimeInput;
210
+ }(_react2['default'].Component);
211
+
212
+ TimeInput.propTypes = {
213
+ prefixCls: _propTypes2['default'].string,
214
+ value: _propTypes2['default'].object,
215
+ selectedValue: _propTypes2['default'].object,
216
+ onChange: _propTypes2['default'].func,
217
+ onSelect: _propTypes2['default'].func,
218
+ placeholder: _propTypes2['default'].string,
219
+ inputMode: _propTypes2['default'].string,
220
+ format: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].arrayOf(_propTypes2['default'].string)]),
221
+ disabled: _propTypes2['default'].bool,
222
+ className: _propTypes2['default'].string,
223
+ showFromSelected: _propTypes2['default'].bool
224
+ };
225
+ TimeInput.defaultProps = {
226
+ format: 'HH:mm',
227
+ placeholder: 'HH:mm'
228
+ };
229
+
230
+
231
+ (0, _reactLifecyclesCompat.polyfill)(TimeInput);
232
+
233
+ exports['default'] = TimeInput;
234
+ module.exports = exports['default'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/seafile-calendar",
3
- "version": "0.1.2-beta.0",
3
+ "version": "1.0.0-alpha.0",
4
4
  "description": "React Calendar",
5
5
  "keywords": [
6
6
  "react",