beyond-rails 0.0.245 → 0.0.246

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.
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