beyond-rails 0.0.245 → 0.0.246

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14a11baddc8aa18a29a74c0774442e2b5486b49ad44a7e435497176aa8a0c230
4
- data.tar.gz: 92a0ac4ab51c30bac1f93cc092bb05c6ac4fd4e0c53eb792b983e967dd77f0a9
3
+ metadata.gz: ebefc15d0cab8d8554a18f030ae3041af23f3aab56633bd12aa9e80f823454d9
4
+ data.tar.gz: a54e416999fce854ecdcc3194d3e7226475f56f8d3ae63d59d638a1651eb8751
5
5
  SHA512:
6
- metadata.gz: 480156108ca39681b88309ac8554648af5d2aa47dfcf9ee077a940f19f4fd87de40a3a630d5a9b81a3a5244529ca07d377ef94f7ff64a3189bd6a065e76c0cff
7
- data.tar.gz: 1b458994269fcc000dd7e5b670e7c69cb816fe56e251a51b55ff7ce78a6925c6951df7897c1f21e86dc5d130def90f4d71c60167ec515ff1b3c0eb4d3cf1c482
6
+ metadata.gz: acb1c4dba756a4d2fa6a0ca378c02e52d2ffb7703bc5d13d1ff298e9604e76250c7124066918e7b45809355f358d100f2b8a293be81292ec00579d93a91433f9
7
+ data.tar.gz: 78dc63e30de5eb027bba31a7cbdefe1c9737774f3090dc69a3f2e243a3d2ffd9a2bb17a33248e6f1d5c5928b5558f50629d460fac15e5eef96d2a4bfb8b66604
@@ -0,0 +1,75 @@
1
+ import { DEFAULT_TIMEZONE } from '../consts'
2
+ import supportDom from '../decorators/supportDom'
3
+ import isTouchDevice from '../utils/isTouchDevice'
4
+ import { format } from '../utils'
5
+
6
+ @supportDom
7
+ export default class MonthInput {
8
+
9
+ constructor(dom, date, options = {}) {
10
+ this.active = false
11
+ this.danger = false
12
+ this.dom = dom
13
+ this.date = date
14
+ this.options = options
15
+ this.tz = options.tz || DEFAULT_TIMEZONE
16
+ this.datePattern = options.datePattern || 'yyyy/MM'
17
+ this.init()
18
+ }
19
+
20
+ focus() {
21
+ this.dom.focus()
22
+ }
23
+
24
+ init() {
25
+ this.initInput()
26
+ this.addEvents()
27
+ }
28
+
29
+ initInput() {
30
+ const { dom } = this
31
+ if (this.date) {
32
+ dom.value = this.format(this.date)
33
+ }
34
+ if (! dom.hasAttribute('placeholder')) {
35
+ dom.setAttribute('placeholder', this.datePattern.toUpperCase())
36
+ }
37
+ if (isTouchDevice()) {
38
+ dom.setAttribute('readonly', 'readonly')
39
+ }
40
+ }
41
+
42
+ format(date) {
43
+ return format(date, this.datePattern, { timezone: this.tz })
44
+ }
45
+
46
+ setDate(date) {
47
+ this.date = date
48
+ this.dom.value = date ? this.format(date) : ''
49
+ }
50
+
51
+ setActive(active) {
52
+ this.active = active
53
+ const func = active ? 'add' : 'remove'
54
+ this.dom.classList[func]('active')
55
+ }
56
+
57
+ setDanger(danger) {
58
+ this.danger = danger
59
+ const func = danger ? 'add' : 'remove'
60
+ this.dom.classList[func]('danger')
61
+ }
62
+
63
+ clearStatus() {
64
+ this.setActive(false)
65
+ this.setDanger(false)
66
+ }
67
+
68
+ addEvents() {
69
+ const { dom } = this
70
+ this.addEvent(dom, 'click', event => this.fire('click', event))
71
+ this.addEvent(dom, 'focus', event => this.fire('focus', event))
72
+ this.addEvent(dom, 'keyup', event => this.fire('keyup', event))
73
+ this.addEvent(dom, 'blur', event => this.fire('blur', event))
74
+ }
75
+ }
@@ -0,0 +1,262 @@
1
+ import supportDom from '../decorators/supportDom'
2
+ import getFloatedTargetPos from '../utils/getFloatedTargetPos'
3
+ import isTouchDevice from '../utils/isTouchDevice'
4
+ import { DEFAULT_TIMEZONE, DEFAULT_LOCALE } from '../consts'
5
+ import {
6
+ chunk,
7
+ format,
8
+ range,
9
+ setYear,
10
+ setMonth,
11
+ getYear,
12
+ getMonth,
13
+ addYears,
14
+ toPixel,
15
+ subYears,
16
+ noop
17
+ } from '../utils'
18
+
19
+ @supportDom
20
+ export default class MonthMenu {
21
+
22
+ constructor(options = {}) {
23
+ const { dom, date } = options
24
+ this.container = dom
25
+ this.date = date
26
+ this.menuDate = this.date || new Date()
27
+ this.options = options
28
+ this.tz = options.tz || DEFAULT_TIMEZONE
29
+ this.locale = options.locale || DEFAULT_LOCALE
30
+ this.change = options.change || noop
31
+ this.isVisible = false
32
+ this.loopIndex = 0
33
+ this.init()
34
+ }
35
+
36
+ init() {
37
+ this.addMenu()
38
+ this.addEvents()
39
+ }
40
+
41
+ renderTableContent() {
42
+ const { date, menuDate, locale } = this
43
+
44
+ const currentYear = date ? getYear(date) : null
45
+ const currentMonth = date ? getMonth(date) : null
46
+
47
+ return chunk(range(0, 12), 3)
48
+ .map(months => {
49
+ const tds = months.map(month => {
50
+ const d = setMonth(menuDate, month)
51
+ const text = format(d, 'MMM', { locale })
52
+
53
+ const isCurrentMonth = (currentYear === getYear(d)) && (currentMonth === getMonth(d))
54
+
55
+ const classname = isCurrentMonth ? 'cell selected-ex' : 'cell'
56
+ return `<td class="${classname}" data-month-td="${month}">${text}</td>`
57
+ }).join('')
58
+ return `<tr>${tds}</tr>`
59
+ })
60
+ .join('')
61
+ }
62
+
63
+ updateTableContent() {
64
+ this.table.innerHTML = this.renderTableContent()
65
+ }
66
+
67
+ addMenu() {
68
+ const { container } = this
69
+ const dom = document.createElement('div')
70
+ dom.classList.add('month-menu')
71
+
72
+ if (container) {
73
+ dom.classList.add('static')
74
+ }
75
+ const title = getYear(this.menuDate)
76
+ dom.innerHTML = `
77
+ <div class="month-menu-content">
78
+ <div class="month-menu-caption">
79
+ <button class="month-menu-caption-btn"
80
+ type="button"
81
+ data-prev-month-btn>
82
+ <i class="icon-chevron-left"></i>
83
+ </button>
84
+ <div data-month-menu-title>${title}</div>
85
+ <button class="month-menu-caption-btn"
86
+ type="button"
87
+ data-next-month-btn>
88
+ <i class="icon-chevron-right"></i>
89
+ </button>
90
+ </div>
91
+ <table class="month-menu-table"
92
+ data-month-table>
93
+ ${this.renderTableContent()}
94
+ </table>
95
+ </div>
96
+ `
97
+ if (container) {
98
+ container.appendChild(dom)
99
+ }
100
+ else {
101
+ document.body.appendChild(dom)
102
+ }
103
+ this.menuTitle = dom.querySelector('[data-month-menu-title]')
104
+ this.prevBtn = dom.querySelector('[data-prev-month-btn]')
105
+ this.nextBtn = dom.querySelector('[data-next-month-btn]')
106
+ this.table = dom.querySelector('[data-month-table]')
107
+ this.dom = dom
108
+ }
109
+
110
+ setTitle(date) {
111
+ this.menuTitle.textContent = getYear(date)
112
+ }
113
+
114
+ addYear(year = 1) {
115
+ this.menuDate = addYears(this.menuDate, year)
116
+ this.setTitle(this.menuDate)
117
+ this.updateTableContent()
118
+ }
119
+
120
+ addYearLoop() {
121
+ const duration = (this.loopIndex === 0) ? 500 : 100
122
+ this.addYearTimer = setTimeout(() => {
123
+ this.loopIndex += 1
124
+ const year = parseInt((this.loopIndex / 5) + 1, 10)
125
+ this.addYear(year)
126
+ this.addYearLoop()
127
+ }, duration)
128
+ }
129
+
130
+ clearAddYearLoop() {
131
+ clearTimeout(this.addYearTimer)
132
+ this.loopIndex = 0
133
+ }
134
+
135
+ subYear(year = 1) {
136
+ this.menuDate = subYears(this.menuDate, year)
137
+ this.setTitle(this.menuDate)
138
+ this.updateTableContent()
139
+ }
140
+
141
+ subYearLoop() {
142
+ const duration = (this.loopIndex === 0) ? 500 : 100
143
+ this.subYearTimer = setTimeout(() => {
144
+ this.loopIndex += 1
145
+ const year = parseInt((this.loopIndex / 5) + 1, 10)
146
+ const currentYear = getYear(this.menuDate)
147
+ if ((currentYear - year) > 0) {
148
+ this.subYear(year)
149
+ this.subYearLoop()
150
+ }
151
+ }, duration)
152
+ }
153
+
154
+ clearSubYearLoop() {
155
+ clearTimeout(this.subYearTimer)
156
+ this.loopIndex = 0
157
+ }
158
+
159
+ stop(event) {
160
+ event.preventDefault()
161
+ event.stopPropagation()
162
+ }
163
+
164
+ addEvents() {
165
+ const isTouch = isTouchDevice()
166
+ const downEvent = isTouch ? 'touchstart' : 'mousedown'
167
+
168
+ this.addEvent(this.prevBtn, downEvent, event => {
169
+ this.stop(event)
170
+ const currentYear = getYear(this.menuDate)
171
+ if ((currentYear - 1) <= 0) {
172
+ return
173
+ }
174
+ this.subYear()
175
+ this.subYearLoop()
176
+ })
177
+
178
+ this.addEvent(this.nextBtn, 'click', event => event.stopPropagation())
179
+ this.addEvent(this.prevBtn, 'click', event => event.stopPropagation())
180
+
181
+ this.addEvent(this.nextBtn, downEvent, event => {
182
+ this.stop(event)
183
+ this.addYear()
184
+ this.addYearLoop()
185
+ })
186
+
187
+ const upEvent = isTouch ? 'touchend' : 'mouseup'
188
+ this.addEvent(this.prevBtn, upEvent, event => {
189
+ this.stop(event)
190
+ this.clearSubYearLoop()
191
+ })
192
+ this.addEvent(this.nextBtn, upEvent, event => {
193
+ this.stop(event)
194
+ this.clearAddYearLoop()
195
+ })
196
+
197
+ this.addEvent(this.table, 'click', event => {
198
+ this.stop(event)
199
+ const { target } = event
200
+ if ('monthTd' in target.dataset) {
201
+ const year = getYear(this.menuDate)
202
+ const month = parseInt(target.dataset.monthTd, 10)
203
+
204
+ if (! this.date) {
205
+ this.date = new Date(this.menuDate.getTime())
206
+ }
207
+
208
+ this.date = setYear(this.date, year)
209
+ this.date = setMonth(this.date, month)
210
+ this.updateTableContent()
211
+ this.emitChange()
212
+ }
213
+ })
214
+ }
215
+
216
+ setDate(date) {
217
+ this.date = date
218
+ this.menuDate = date
219
+ this.setTitle(date)
220
+ this.updateTableContent()
221
+ }
222
+
223
+ emitChange() {
224
+ this.change(this.date)
225
+ }
226
+
227
+ pos(src) {
228
+ const { dom } = this
229
+ const { pos } = getFloatedTargetPos({
230
+ src,
231
+ target: dom,
232
+ place: 'bottom',
233
+ align: 'left',
234
+ offset: 4
235
+ })
236
+ dom.style.left = toPixel(pos.left)
237
+ dom.style.top = toPixel(pos.top)
238
+ }
239
+
240
+ show(src) {
241
+ const { dom } = this
242
+ dom.style.display = 'block'
243
+ if (src) {
244
+ this.pos(src)
245
+ }
246
+ dom.style.opacity = 1
247
+ this.isVisible = true
248
+ }
249
+
250
+ hide() {
251
+ this.dom.style.display = 'none'
252
+ this.isVisible = false
253
+ }
254
+
255
+ destroy() {
256
+ this.menuTitle = null
257
+ this.prevBtn = null
258
+ this.nextBtn = null
259
+ this.table = null
260
+ this.dom.remove()
261
+ }
262
+ }
@@ -0,0 +1,90 @@
1
+ import MonthInput from './MonthInput'
2
+ import MonthMenu from './MonthMenu'
3
+ import supportDom from '../decorators/supportDom'
4
+ import { DEFAULT_TIMEZONE } from '../consts'
5
+ import { noop, parse } from '../utils'
6
+
7
+ @supportDom
8
+ export default class Monthpicker {
9
+
10
+ constructor(dom, options = {}) {
11
+ this.dom = dom
12
+ this.tz = options.tz || DEFAULT_TIMEZONE
13
+ this.date = options.date
14
+ this.menuDate = this.date
15
+
16
+ this.options = options
17
+ this.backdropMode = options.backdropMode || 'auto'
18
+ this.change = options.change || noop
19
+ this.init()
20
+ }
21
+
22
+ init() {
23
+ const { dom } = this
24
+ this.monthInput = new MonthInput(
25
+ dom.querySelector('[data-month]'),
26
+ this.date,
27
+ this.options
28
+ )
29
+ this.monthMenu = new MonthMenu({
30
+ date: this.menuDate,
31
+ change: date => {
32
+ this.monthInput.setDate(date)
33
+ this.monthInput.clearStatus()
34
+ this.monthMenu.hide()
35
+ }
36
+ })
37
+ this.addEvents()
38
+ }
39
+
40
+ handleMonthInputFocus() {
41
+ const { monthInput } = this
42
+ monthInput.clearStatus()
43
+ monthInput.setActive(true)
44
+ this.monthMenu.show(this.dom)
45
+ }
46
+
47
+ handleMonthInputKeyUp(event) {
48
+ const { monthInput } = this
49
+ const { value } = event.target
50
+ const res = parse(value, monthInput.datePattern, this.date)
51
+
52
+ if (res.toString() === 'Invalid Date') {
53
+ monthInput.setDanger(true)
54
+ this.nextDate = null
55
+ }
56
+ else {
57
+ monthInput.setDanger(false)
58
+ this.nextDate = res
59
+ }
60
+ }
61
+
62
+ handleMonthInputBlur() {
63
+ if (this.nextDate) {
64
+ this.date = this.nextDate
65
+ this.menuDate = this.date
66
+ this.monthMenu.setDate(this.menuDate)
67
+ this.nextDate = null
68
+ }
69
+ }
70
+
71
+ addEvents() {
72
+ const { monthInput } = this
73
+ monthInput.on('focus', () => this.handleMonthInputFocus())
74
+ monthInput.on('click', event => event.stopPropagation())
75
+ monthInput.on('keyup', event => this.handleMonthInputKeyUp(event))
76
+ monthInput.on('blur', () => this.handleMonthInputBlur())
77
+
78
+ if (this.backdropMode === 'auto') {
79
+ this.addEvent(document, 'click', () => {
80
+ this.monthMenu.hide()
81
+ this.monthInput.clearStatus()
82
+ })
83
+ }
84
+ }
85
+
86
+ destroy() {
87
+ this.monthInput.destroy()
88
+ this.monthMenu.destroy()
89
+ }
90
+ }
@@ -14,6 +14,8 @@ import DateTimeRanger from './components/DateTimeRanger'
14
14
  import Datepicker from './components/Datepicker'
15
15
  import Dropdown from './components/Dropdown'
16
16
  import LineChart from './components/LineChart'
17
+ import Monthpicker from './components/Monthpicker'
18
+ import MonthMenu from './components/MonthMenu'
17
19
  import Menu from './components/Menu'
18
20
  import Modal from './components/Modal'
19
21
  import Navbar from './components/Navbar'
@@ -51,6 +53,8 @@ export {
51
53
  Datepicker,
52
54
  Dropdown,
53
55
  LineChart,
56
+ Monthpicker,
57
+ MonthMenu,
54
58
  Menu,
55
59
  Modal,
56
60
  Navbar,
@@ -9,6 +9,8 @@ import toPixel from '@superlanding/topixel'
9
9
  // date-fns
10
10
  import addDays from 'date-fns/addDays'
11
11
  import addMonths from 'date-fns/addMonths'
12
+ import subYears from 'date-fns/subYears'
13
+ import addYears from 'date-fns/addYears'
12
14
  import compareAsc from 'date-fns/compareAsc'
13
15
  import endOfDay from 'date-fns/endOfDay'
14
16
  import endOfMonth from 'date-fns/endOfMonth'
@@ -18,9 +20,11 @@ import getHours from 'date-fns/getHours'
18
20
  import getMinutes from 'date-fns/getMinutes'
19
21
  import getMonth from 'date-fns/getMonth'
20
22
  import getSeconds from 'date-fns/getSeconds'
23
+ import setYear from 'date-fns/setYear'
21
24
  import getYear from 'date-fns/getYear'
22
25
  import parse from 'date-fns/parse'
23
26
  import set from 'date-fns/set'
27
+ import setMonth from 'date-fns/setMonth'
24
28
  import startOfDay from 'date-fns/startOfDay'
25
29
  import startOfMonth from 'date-fns/startOfMonth'
26
30
  import subMonths from 'date-fns/subMonths'
@@ -28,6 +32,7 @@ import toDate from 'date-fns/toDate'
28
32
  import { format } from 'date-fns-tz'
29
33
 
30
34
  // lodash
35
+ import chunk from 'lodash.chunk'
31
36
  import debounce from 'lodash.debounce'
32
37
  import isFunction from 'lodash.isfunction'
33
38
  import noop from 'lodash.noop'
@@ -50,6 +55,8 @@ export {
50
55
  // date-fns
51
56
  addDays,
52
57
  addMonths,
58
+ addYears,
59
+ subYears,
53
60
  compareAsc,
54
61
  endOfDay,
55
62
  endOfMonth,
@@ -59,9 +66,11 @@ export {
59
66
  getMinutes,
60
67
  getMonth,
61
68
  getSeconds,
69
+ setYear,
62
70
  getYear,
63
71
  parse,
64
72
  set,
73
+ setMonth,
65
74
  startOfDay,
66
75
  startOfMonth,
67
76
  subMonths,
@@ -69,6 +78,7 @@ export {
69
78
  format,
70
79
 
71
80
  // lodash
81
+ chunk,
72
82
  debounce,
73
83
  isFunction,
74
84
  noop,
@@ -26,6 +26,7 @@
26
26
  @import './components/_checkbox';
27
27
  @import './components/_date-input';
28
28
  @import './components/_date-menu';
29
+ @import './components/_month-menu';
29
30
  @import './components/_date-time-ranger';
30
31
  @import './components/_datepicker';
31
32
  @import './components/_dropdown';
@@ -0,0 +1,70 @@
1
+ .month-menu {
2
+ display: none;
3
+ position: absolute;
4
+ box-shadow: 0 0 0 1px rgba(136, 152, 170, .1),
5
+ 0 15px 35px 0 rgba(49, 49, 93, .1),
6
+ 0 5px 15px 0 rgba(0, 0, 0, .08);
7
+ background-color: #fff;
8
+ white-space: nowrap;
9
+ &.static {
10
+ display: inline-block;
11
+ position: static;
12
+ }
13
+ .month-menu-content {
14
+ display: inline-block;
15
+ position: relative;
16
+ padding: 0 14px 14px 14px;
17
+ width: 252px;
18
+ }
19
+ .month-menu-caption {
20
+ display: flex;
21
+ justify-content: space-between;
22
+ font-size: 15px;
23
+ color: #3c4257;
24
+ text-align: center;
25
+ height: 50px;
26
+ line-height: 50px;
27
+ }
28
+ .month-menu-caption-btn {
29
+ border: 0;
30
+ background-color: transparent;
31
+ display: block;
32
+ @include size(50px);
33
+
34
+ .icon-chevron-left,
35
+ .icon-chevron-right {
36
+ font-size: 12px;
37
+ }
38
+ }
39
+ .month-menu-table {
40
+ font-size: 14px;
41
+ width: 100%;
42
+ margin-top: 2px;
43
+ th, td {
44
+ padding: 3px;
45
+ }
46
+ td {
47
+ text-align: center;
48
+ &.cell {
49
+ background-color: #f7fafc;
50
+ cursor: pointer;
51
+ border-width: 1px;
52
+ border-style: solid;
53
+ border-color: #e3e8ee;
54
+ }
55
+ &.cell.today {
56
+ background-color: #fffef4;
57
+ }
58
+ &.cell.selected {
59
+ background-color: #6c8eef;
60
+ color: #fff;
61
+ border-color: #6c8eef;
62
+ }
63
+ &.cell.selected-ex {
64
+ background-color: #5469d4;
65
+ color: #fff;
66
+ border-color: #5469d4;
67
+ }
68
+ }
69
+ }
70
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beyond-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.245
4
+ version: 0.0.246
5
5
  platform: ruby
6
6
  authors:
7
7
  - kmsheng
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-09 00:00:00.000000000 Z
12
+ date: 2020-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sassc
@@ -139,6 +139,9 @@ files:
139
139
  - src/js/components/LineChart.js
140
140
  - src/js/components/Menu.js
141
141
  - src/js/components/Modal.js
142
+ - src/js/components/MonthInput.js
143
+ - src/js/components/MonthMenu.js
144
+ - src/js/components/Monthpicker.js
142
145
  - src/js/components/Navbar.js
143
146
  - src/js/components/PieChart.js
144
147
  - src/js/components/Radio.js
@@ -235,6 +238,7 @@ files:
235
238
  - src/sass/components/_list.scss
236
239
  - src/sass/components/_mega-menu.scss
237
240
  - src/sass/components/_modal.scss
241
+ - src/sass/components/_month-menu.scss
238
242
  - src/sass/components/_nav.scss
239
243
  - src/sass/components/_navbar.scss
240
244
  - src/sass/components/_pagination.scss