beyond-rails 0.0.139

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