beyond-rails 0.0.139

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/src/font/icomoon.eot +0 -0
  3. data/src/font/icomoon.svg +125 -0
  4. data/src/font/icomoon.ttf +0 -0
  5. data/src/font/icomoon.woff +0 -0
  6. data/src/img/black-cat.svg +15 -0
  7. data/src/img/cart.svg +16 -0
  8. data/src/img/china-flag.svg +16 -0
  9. data/src/img/ecpay.svg +12 -0
  10. data/src/img/family-mart.svg +13 -0
  11. data/src/img/fb-messenger.svg +12 -0
  12. data/src/img/fb.svg +10 -0
  13. data/src/img/hct.svg +16 -0
  14. data/src/img/hi-life.svg +23 -0
  15. data/src/img/line.svg +14 -0
  16. data/src/img/ok-mart.svg +9 -0
  17. data/src/img/pelican.svg +33 -0
  18. data/src/img/seven-eleven.svg +13 -0
  19. data/src/img/smilepay.svg +13 -0
  20. data/src/img/taiwan-flag.svg +17 -0
  21. data/src/js/components/Alert.js +23 -0
  22. data/src/js/components/Autocomplete.js +110 -0
  23. data/src/js/components/AutocompleteMenu.js +88 -0
  24. data/src/js/components/Btn.js +41 -0
  25. data/src/js/components/Checkbox.js +24 -0
  26. data/src/js/components/DateInput.js +74 -0
  27. data/src/js/components/DateMenu.js +370 -0
  28. data/src/js/components/DateTimeRanger.js +436 -0
  29. data/src/js/components/Datepicker.js +250 -0
  30. data/src/js/components/DatepickerBtnArrow.js +18 -0
  31. data/src/js/components/Dropdown.js +137 -0
  32. data/src/js/components/Menu.js +43 -0
  33. data/src/js/components/Modal.js +76 -0
  34. data/src/js/components/Navbar.js +47 -0
  35. data/src/js/components/Radio.js +24 -0
  36. data/src/js/components/SearchDropdown.js +339 -0
  37. data/src/js/components/Sidebar.js +56 -0
  38. data/src/js/components/Tabbox.js +229 -0
  39. data/src/js/components/TimeInput.js +71 -0
  40. data/src/js/components/TimeMenu.js +117 -0
  41. data/src/js/components/Toast.js +47 -0
  42. data/src/js/components/ToastItem.js +62 -0
  43. data/src/js/components/Tooltip.js +94 -0
  44. data/src/js/consts/createdComponents.js +1 -0
  45. data/src/js/consts/index.js +5 -0
  46. data/src/js/helpers/bind.js +53 -0
  47. data/src/js/helpers/dateEq.js +5 -0
  48. data/src/js/helpers/dateGt.js +5 -0
  49. data/src/js/helpers/dateLt.js +5 -0
  50. data/src/js/helpers/docReady.js +10 -0
  51. data/src/js/helpers/getFloatedTargetPos.js +250 -0
  52. data/src/js/helpers/getKey.js +14 -0
  53. data/src/js/helpers/isTouchDevice.js +3 -0
  54. data/src/js/helpers/msToS.js +3 -0
  55. data/src/js/helpers/promisify.js +9 -0
  56. data/src/js/helpers/range.js +7 -0
  57. data/src/js/helpers/supportDom.js +46 -0
  58. data/src/js/helpers/toPixel.js +3 -0
  59. data/src/js/helpers/unbindAll.js +6 -0
  60. data/src/js/index.js +47 -0
  61. data/src/js/jquery/bindAlertFn.js +13 -0
  62. data/src/js/jquery/bindAutocompleteFn.js +13 -0
  63. data/src/js/jquery/bindBtnFn.js +17 -0
  64. data/src/js/jquery/bindCheckboxFn.js +13 -0
  65. data/src/js/jquery/bindDateTimeRangerFn.js +14 -0
  66. data/src/js/jquery/bindDatepickerFn.js +14 -0
  67. data/src/js/jquery/bindDropdownFn.js +14 -0
  68. data/src/js/jquery/bindMenuFn.js +13 -0
  69. data/src/js/jquery/bindModalFn.js +14 -0
  70. data/src/js/jquery/bindNavbarFn.js +13 -0
  71. data/src/js/jquery/bindRadioFn.js +13 -0
  72. data/src/js/jquery/bindSearchDropdownFn.js +14 -0
  73. data/src/js/jquery/bindSidebarFn.js +13 -0
  74. data/src/js/jquery/bindTabboxFn.js +13 -0
  75. data/src/js/jquery/bindToastFn.js +6 -0
  76. data/src/js/jquery/bindTooltipFn.js +13 -0
  77. data/src/js/jquery/index.js +52 -0
  78. data/src/js/polyfills/classList.js +263 -0
  79. data/src/js/polyfills/elementDataset.js +3 -0
  80. data/src/js/polyfills/nodeContains.js +17 -0
  81. data/src/js/polyfills/nodeHasAttribute.js +5 -0
  82. data/src/js/polyfills/nodeRemove.js +19 -0
  83. data/src/sass/_beyond-sprockets.scss +1 -0
  84. data/src/sass/_beyond.scss +50 -0
  85. data/src/sass/_main.scss +141 -0
  86. data/src/sass/abstracts/_mixins.scss +129 -0
  87. data/src/sass/abstracts/_placeholders.scss +43 -0
  88. data/src/sass/abstracts/_variables.scss +355 -0
  89. data/src/sass/base/_background.scss +10 -0
  90. data/src/sass/base/_typography.scss +183 -0
  91. data/src/sass/components/_alert.scss +50 -0
  92. data/src/sass/components/_autocomplete.scss +29 -0
  93. data/src/sass/components/_avatar.scss +28 -0
  94. data/src/sass/components/_badge.scss +29 -0
  95. data/src/sass/components/_breadcrumb.scss +17 -0
  96. data/src/sass/components/_btn-group.scss +19 -0
  97. data/src/sass/components/_btn.scss +172 -0
  98. data/src/sass/components/_card.scss +183 -0
  99. data/src/sass/components/_checkbox.scss +99 -0
  100. data/src/sass/components/_date-input.scss +28 -0
  101. data/src/sass/components/_date-menu.scss +85 -0
  102. data/src/sass/components/_date-time-ranger.scss +21 -0
  103. data/src/sass/components/_datepicker.scss +3 -0
  104. data/src/sass/components/_dropdown.scss +144 -0
  105. data/src/sass/components/_form.scss +383 -0
  106. data/src/sass/components/_icon.scss +371 -0
  107. data/src/sass/components/_input.scss +48 -0
  108. data/src/sass/components/_list.scss +23 -0
  109. data/src/sass/components/_modal.scss +72 -0
  110. data/src/sass/components/_nav.scss +75 -0
  111. data/src/sass/components/_navbar.scss +211 -0
  112. data/src/sass/components/_pagination.scss +64 -0
  113. data/src/sass/components/_radio.scss +71 -0
  114. data/src/sass/components/_search-dropdown.scss +28 -0
  115. data/src/sass/components/_select.scss +54 -0
  116. data/src/sass/components/_sidebar.scss +35 -0
  117. data/src/sass/components/_spinner.scss +79 -0
  118. data/src/sass/components/_tabbox.scss +83 -0
  119. data/src/sass/components/_table.scss +65 -0
  120. data/src/sass/components/_tag.scss +43 -0
  121. data/src/sass/components/_time-input.scss +28 -0
  122. data/src/sass/components/_time-menu.scss +24 -0
  123. data/src/sass/components/_toast.scss +51 -0
  124. data/src/sass/components/_tooltip.scss +10 -0
  125. data/src/sass/img/arrow-dropdown.svg +4 -0
  126. data/src/sass/img/arrow-select-ex.svg +18 -0
  127. data/src/sass/img/arrow-select.svg +18 -0
  128. data/src/sass/layout/_border-util.scss +36 -0
  129. data/src/sass/layout/_col.scss +90 -0
  130. data/src/sass/layout/_container.scss +44 -0
  131. data/src/sass/layout/_flex-util.scss +18 -0
  132. data/src/sass/layout/_offset-util.scss +20 -0
  133. data/src/sass/layout/_sizing-util.scss +14 -0
  134. data/src/sass/layout/_spacing-util.scss +9 -0
  135. data/src/sass/layout/_visibility-util.scss +25 -0
  136. data/src/sass/vendor/_normalize.scss +578 -0
  137. data/src/sass/vendor/_turbolink.scss +5 -0
  138. metadata +235 -0
@@ -0,0 +1,56 @@
1
+ import supportDom from '../helpers/supportDom'
2
+
3
+ @supportDom
4
+ export default class Sidebar {
5
+
6
+ constructor(dom) {
7
+ this.btn = dom
8
+ this.sidebar = document.querySelector(`[data-sidebar="${dom.dataset.sidebarOpener}"]`)
9
+ this.isVisible = false
10
+ this.init()
11
+ }
12
+
13
+ init() {
14
+ this.addBackdrop()
15
+ this.addEvents()
16
+ }
17
+
18
+ addBackdrop() {
19
+ if (this.backdrop) {
20
+ return
21
+ }
22
+ const backdrop = document.createElement('div')
23
+ backdrop.className = 'backdrop'
24
+ document.body.appendChild(backdrop)
25
+ this.backdrop = backdrop
26
+ }
27
+
28
+ showBackdrop() {
29
+ this.backdrop.classList.add('opened')
30
+ }
31
+
32
+ hideBackdrop() {
33
+ this.backdrop.classList.remove('opened')
34
+ }
35
+
36
+ show() {
37
+ this.showBackdrop()
38
+ this.sidebar.classList.add('opened')
39
+ this.isVisible = true
40
+ }
41
+
42
+ hide() {
43
+ this.hideBackdrop()
44
+ this.sidebar.classList.remove('opened')
45
+ this.isVisible = false
46
+ }
47
+
48
+ addEvents() {
49
+ this.addEvent(this.btn, 'click', () => this.show())
50
+ this.addEvent(this.backdrop, 'click', () => this.hide())
51
+ }
52
+
53
+ destroy() {
54
+ this.backdrop.remove()
55
+ }
56
+ }
@@ -0,0 +1,229 @@
1
+ import noop from 'lodash.noop'
2
+ import supportDom from '../helpers/supportDom'
3
+ import Dropdown from './Dropdown'
4
+
5
+ @supportDom
6
+ export default class Tabbox {
7
+
8
+ constructor(dom, options = {}) {
9
+ this.currentNode = null
10
+ this.optionEl = null
11
+ this.dom = dom
12
+ this.options = options
13
+ this.options.change = options.change || noop
14
+ this.options.click = options.click || noop
15
+ this.init()
16
+ }
17
+
18
+ init() {
19
+ const { dom } = this
20
+ this.btns = Array.from(dom.querySelectorAll('button[data-tabbox-item]'))
21
+ this.dropdownBtns = Array.from(dom.querySelectorAll('button[data-tabbox-dropdown]'))
22
+ this.addEvents()
23
+ this.appendSlider()
24
+ }
25
+
26
+ adjustSlider() {
27
+ const [firstBtn] = this.btns
28
+ if (! firstBtn) {
29
+ return
30
+ }
31
+ const { slider } = this
32
+ slider.style.top = (firstBtn.offsetHeight - slider.offsetHeight) + 'px'
33
+ slider.style.left = firstBtn.offsetLeft + 'px'
34
+ }
35
+
36
+ moveTo(name) {
37
+ const target = this.dom.querySelector(`[data-tabbox-item=${name}]`)
38
+ if (target) {
39
+ this.removeCurrentClass()
40
+ this.currentNode = target
41
+ this.moveToCurrentNode()
42
+ this.addCurrentClass()
43
+ }
44
+ }
45
+
46
+ eachDropdownOption(fn) {
47
+ let index = 0
48
+ for (const d of this.dropdownInstances) {
49
+ const options = Array.from(d.menu.querySelectorAll('[data-tabbox-item]'))
50
+ for (const optionEl of options) {
51
+ const going = fn({
52
+ dropdownBtn: this.dropdownBtns[index],
53
+ dropdownInstance: d,
54
+ optionEl
55
+ })
56
+ if (going === false) {
57
+ return
58
+ }
59
+ }
60
+ ++index
61
+ }
62
+ }
63
+
64
+ getDefaultDropdownData() {
65
+
66
+ let res = {}
67
+
68
+ this.eachDropdownOption(({ dropdownBtn, dropdownInstance, optionEl }) => {
69
+ if ('default' in optionEl.dataset) {
70
+ res = {
71
+ defaultDropdownBtn: dropdownBtn,
72
+ defaultDropdownInstance: dropdownInstance,
73
+ defaultOptionEl: optionEl
74
+ }
75
+ return false
76
+ }
77
+ })
78
+ return res
79
+ }
80
+
81
+ appendSlider() {
82
+ this.slider = document.createElement('div')
83
+ this.slider.classList.add('js-slider')
84
+ this.dom.appendChild(this.slider)
85
+ const defaultBtn = this.btns.find(btn => 'default' in btn.dataset)
86
+
87
+ this.adjustSlider()
88
+
89
+ if (defaultBtn) {
90
+ this.currentNode = defaultBtn || defaultSelectBox
91
+ this.moveToCurrentNode()
92
+ this.addCurrentClass()
93
+ }
94
+
95
+ const { defaultDropdownBtn, defaultDropdownInstance,
96
+ defaultOptionEl } = this.getDefaultDropdownData()
97
+
98
+ if (defaultDropdownBtn) {
99
+ this.currentNode = defaultDropdownBtn
100
+ this.optionEl = defaultOptionEl
101
+ this.moveToCurrentNode()
102
+ this.addCurrentClass()
103
+ defaultDropdownInstance.setText(this.optionEl.textContent)
104
+ }
105
+ }
106
+
107
+ setSliderColor(color) {
108
+ this.slider.style.backgroundColor = color
109
+ }
110
+
111
+ moveToCurrentNode() {
112
+ const node = this.currentNode
113
+ if (! node) {
114
+ return
115
+ }
116
+ if ('tabboxDropdown' in node.dataset) {
117
+ return this.moveSlider({
118
+ top: node.offsetTop,
119
+ left: node.offsetLeft,
120
+ width: node.offsetWidth,
121
+ color: this.optionEl.dataset.activeColor
122
+ })
123
+ }
124
+ this.moveSlider({
125
+ top: node.offsetTop,
126
+ left: node.offsetLeft,
127
+ width: node.offsetWidth,
128
+ color: node.dataset.activeColor
129
+ })
130
+ }
131
+
132
+ moveSlider({ top, left, width, color = '#858585' }) {
133
+ this.slider.style.transform = `translate(${left}px, ${top}px)`
134
+ this.slider.style.width = width + 'px'
135
+ this.slider.style.backgroundColor = color
136
+ }
137
+
138
+ removeCurrentClass() {
139
+ if (this.currentNode) {
140
+ this.currentNode.classList.remove('js-current')
141
+ }
142
+ }
143
+
144
+ addCurrentClass() {
145
+ if (this.currentNode) {
146
+ this.currentNode.classList.add('js-current')
147
+ }
148
+ }
149
+
150
+ setStatus(status) {
151
+ const btn = this.btns.find(btn => btn.dataset.tabboxItem === status)
152
+ if (btn) {
153
+ this.removeCurrentClass()
154
+ this.currentNode = btn
155
+ this.moveToCurrentNode()
156
+ this.addCurrentClass()
157
+ this.options.change({ id: status, type: 'btn' })
158
+ return
159
+ }
160
+
161
+ let dropdownMatched = false
162
+ this.eachDropdownOption(({ dropdownBtn, dropdownInstance, optionEl }) => {
163
+ if (status === optionEl.dataset.tabboxItem) {
164
+ this.setDropdown({ dropdownBtn, dropdownInstance, optionEl })
165
+ this.options.change({ id: status, type: 'dropdown' })
166
+ dropdownMatched = true
167
+ return false
168
+ }
169
+ })
170
+
171
+ if (! dropdownMatched) {
172
+ throw new Error(`Cannot find status: ${status}`)
173
+ }
174
+ }
175
+
176
+ setDropdown({ dropdownBtn, dropdownInstance, optionEl }) {
177
+ this.currentNode = dropdownBtn
178
+ this.optionEl = optionEl
179
+ this.moveToCurrentNode()
180
+
181
+ this.dropdownInstances.filter(d => d !== dropdownInstance)
182
+ .forEach(d => d.restoreText())
183
+ dropdownInstance.setText(this.optionEl.textContent)
184
+ }
185
+
186
+ addEvents() {
187
+ this.dropdownInstances = this.dropdownBtns.map(el => {
188
+ const dropdownInstance = new Dropdown(el, {
189
+ menuClick: event => {
190
+ const id = event.target.dataset.tabboxItem
191
+ this.options.click({ id, type: 'dropdown' })
192
+
193
+ if (this.optionEl === event.target) {
194
+ return
195
+ }
196
+ this.setDropdown({
197
+ dropdownBtn: el,
198
+ optionEl: event.target,
199
+ dropdownInstance
200
+ })
201
+ this.options.change({ id, type: 'dropdown' })
202
+ }
203
+ })
204
+ return dropdownInstance
205
+ })
206
+
207
+ this.btns.forEach(btn => {
208
+ this.addEvent(btn, 'click', () => {
209
+ const id = btn.dataset.tabboxItem
210
+ this.options.click({ id, type: 'btn' })
211
+ if (btn !== this.currentNode) {
212
+ this.dropdownInstances.forEach(d => d.restoreText())
213
+ this.removeCurrentClass()
214
+ this.currentNode = btn
215
+ this.optionEl = null
216
+ this.moveToCurrentNode()
217
+ this.addCurrentClass()
218
+ this.options.change({ id, type: 'btn' })
219
+ }
220
+ })
221
+ })
222
+ }
223
+
224
+ destroy() {
225
+ this.currentNode = null
226
+ this.dropdownInstances.forEach(d => d.destroy())
227
+ this.slider.parentNode.removeChild(this.slider)
228
+ }
229
+ }
@@ -0,0 +1,71 @@
1
+ import { format } from 'date-fns-tz'
2
+ import { DEFAULT_TIMEZONE } from '../consts'
3
+ import supportDom from '../helpers/supportDom'
4
+ import isTouchDevice from '../helpers/isTouchDevice'
5
+
6
+ @supportDom
7
+ export default class TimeInput {
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.timePattern = options.timePattern || 'HH:mm'
17
+
18
+ this.init()
19
+ }
20
+
21
+ init() {
22
+ this.initInput()
23
+ this.addEvents()
24
+ }
25
+
26
+ initInput() {
27
+ const { dom } = this
28
+ if (this.date) {
29
+ dom.value = this.format(this.date)
30
+ }
31
+ if (! dom.hasAttribute('placeholder')) {
32
+ dom.setAttribute('placeholder', this.timePattern.toUpperCase())
33
+ }
34
+ if (isTouchDevice()) {
35
+ dom.setAttribute('readonly', 'readonly')
36
+ }
37
+ }
38
+
39
+ format(date) {
40
+ return format(date, this.timePattern, { timezone: this.tz })
41
+ }
42
+
43
+ setDate(date) {
44
+ this.date = date
45
+ this.dom.value = date ? this.format(date) : ''
46
+ }
47
+
48
+ setActive(active) {
49
+ this.active = active
50
+ const func = active ? 'add' : 'remove'
51
+ this.dom.classList[func]('active')
52
+ }
53
+
54
+ setDanger(danger) {
55
+ this.danger = danger
56
+ const func = danger ? 'add' : 'remove'
57
+ this.dom.classList[func]('danger')
58
+ }
59
+
60
+ clearStatus() {
61
+ this.setActive(false)
62
+ this.setDanger(false)
63
+ }
64
+
65
+ addEvents() {
66
+ const { dom } = this
67
+ this.addEvent(dom, 'focus', event => this.fire('focus', event))
68
+ this.addEvent(dom, 'keyup', event => this.fire('keyup', event))
69
+ this.addEvent(dom, 'blur', event => this.fire('blur', event))
70
+ }
71
+ }
@@ -0,0 +1,117 @@
1
+ import getHours from 'date-fns/getHours'
2
+ import getMinutes from 'date-fns/getMinutes'
3
+ import getFloatedTargetPos from '../helpers/getFloatedTargetPos'
4
+ import toPixel from '../helpers/toPixel'
5
+ import range from 'lodash.range'
6
+ import supportDom from '../helpers/supportDom'
7
+
8
+ @supportDom
9
+ export default class TimeMenu {
10
+
11
+ constructor() {
12
+ this.date = null
13
+ this.isVisible = false
14
+ this.init()
15
+ }
16
+
17
+ init() {
18
+ this.addMenu()
19
+ this.addEvents()
20
+ }
21
+
22
+ getMenuItems(step) {
23
+ const dayMins = 24 * 60
24
+ return range(0, dayMins, step)
25
+ .reduce((arr, mins) => {
26
+ const hour = parseInt(mins / 60, 10)
27
+ const min = mins % 60
28
+ arr.push({ hour, min })
29
+ return arr
30
+ }, [])
31
+ .map(({ hour, min }) => {
32
+ return `<div class="time-menu-item"
33
+ data-hour="${hour}"
34
+ data-minute="${min}">${hour}:${min.toString().padStart(2, '0')}</div>`
35
+ })
36
+ .join('')
37
+ }
38
+
39
+ addMenu() {
40
+ const dom = document.createElement('div')
41
+ dom.className = 'time-menu'
42
+ document.body.appendChild(dom)
43
+ this.dom = dom
44
+ }
45
+
46
+ addEvents() {
47
+ this.addEvent(this.dom, 'click', event => {
48
+ const { dataset } = event.target
49
+ if ('hour' in dataset) {
50
+ const res = {
51
+ hour: parseInt(dataset.hour, 10),
52
+ minute: parseInt(dataset.minute, 10)
53
+ }
54
+ this.fire('click', event, res)
55
+ }
56
+ })
57
+ }
58
+
59
+ pos(src) {
60
+ const { dom } = this
61
+ const { pos } = getFloatedTargetPos({
62
+ src,
63
+ target: dom,
64
+ place: 'bottom',
65
+ align: 'right',
66
+ offset: 4
67
+ })
68
+ dom.style.left = toPixel(pos.left)
69
+ dom.style.top = toPixel(pos.top)
70
+ }
71
+
72
+ setActiveNode(node, active) {
73
+ if (active) {
74
+ return node.classList.add('active')
75
+ }
76
+ node.classList.remove('active')
77
+ }
78
+
79
+ updateItems(date) {
80
+ const hour = getHours(date).toString()
81
+ const minute = getMinutes(date).toString()
82
+ Array.from(this.dom.childNodes)
83
+ .forEach(node => {
84
+ const { hour: datasetHour, minute: datasetMinute } = node.dataset
85
+ const hourEqualed = (datasetHour === hour)
86
+ const minuteEqualed = (datasetMinute === minute)
87
+
88
+ if (hourEqualed && (datasetMinute === '0')) {
89
+ this.dom.scrollTop = node.offsetTop
90
+ }
91
+ const active = (hourEqualed && minuteEqualed)
92
+ this.setActiveNode(node, active)
93
+ })
94
+ }
95
+
96
+ show({ src, date, step = 30 }) {
97
+ const { dom } = this
98
+ dom.innerHTML = this.getMenuItems(step)
99
+ dom.style.opacity = 0
100
+ dom.style.display = 'block'
101
+ this.pos(src)
102
+ this.updateItems(date)
103
+ dom.style.opacity = 1
104
+ this.isVisible = true
105
+ }
106
+
107
+ hide() {
108
+ this.dom.style.left = '-100%'
109
+ this.dom.style.bottom = '-100%'
110
+ this.dom.style.display = 'none'
111
+ this.isVisible = false
112
+ }
113
+
114
+ destroy() {
115
+ this.dom.remove()
116
+ }
117
+ }