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,47 @@
1
+ import supportDom from '../helpers/supportDom'
2
+ import ToastItem from './ToastItem'
3
+
4
+ @supportDom
5
+ export default class Toast {
6
+
7
+ constructor() {
8
+ this.init()
9
+ }
10
+
11
+ init() {
12
+ const toast = document.createElement('div')
13
+ toast.classList.add('toast')
14
+ document.body.appendChild(toast)
15
+ this.toast = toast
16
+ this.items = []
17
+ }
18
+
19
+ send(arg) {
20
+
21
+ let options = arg
22
+
23
+ if (typeof arg === 'string') {
24
+ options = { message: arg }
25
+ }
26
+
27
+ const toastItem = new ToastItem(options)
28
+ this.toast.appendChild(toastItem.dom)
29
+ this.items.push(toastItem)
30
+
31
+ toastItem._showTimer = setTimeout(() => toastItem.show(), 50)
32
+ toastItem._timer = setTimeout(() => {
33
+ this.items = this.items.filter(item => item !== toastItem)
34
+ toastItem.destroy()
35
+ }, options.duration || 3000)
36
+
37
+ return () => {
38
+ this.items = this.items.filter(item => item !== toastItem)
39
+ toastItem.destroy()
40
+ }
41
+ }
42
+
43
+ destroy() {
44
+ this.items.forEach(item => item.destroy())
45
+ this.toast.remove()
46
+ }
47
+ }
@@ -0,0 +1,62 @@
1
+ import supportDom from '../helpers/supportDom'
2
+
3
+ @supportDom
4
+ export default class ToastItem {
5
+
6
+ constructor(options = {}) {
7
+ this.options = options
8
+ this.init()
9
+ }
10
+
11
+ init() {
12
+
13
+ const { message, btnText, btnCb } = this.options
14
+
15
+ const dom = document.createElement('div')
16
+ dom.innerHTML = `
17
+ <div class="toast-item">
18
+ <div class="toast-message">${message}</div>
19
+ </div>
20
+ `
21
+ dom.className = 'toast-item-box'
22
+
23
+ this.dom = dom
24
+
25
+ if (btnText) {
26
+ this.dom.classList.add('has-btn')
27
+ this.createBtn(btnText)
28
+ }
29
+ if (btnText && btnCb) {
30
+ this.createBtnCb()
31
+ }
32
+ }
33
+
34
+ show() {
35
+ this.dom.classList.add('visible')
36
+ }
37
+
38
+ createBtn() {
39
+ const btn = document.createElement('button')
40
+ btn.className = 'toast-btn'
41
+ btn.innerText = this.options.btnText
42
+ this.dom.querySelector('.toast-item').appendChild(btn)
43
+ this.btn = btn
44
+ }
45
+
46
+ createBtnCb() {
47
+ this.addEvent(this.btn, 'click', () => {
48
+ this.options.btnCb({
49
+ clear: () => {
50
+ this.destroy()
51
+ }
52
+ })
53
+ })
54
+ }
55
+
56
+ destroy() {
57
+ const { dom } = this
58
+ clearTimeout(dom._showTimer)
59
+ clearTimeout(dom._timer)
60
+ dom.remove()
61
+ }
62
+ }
@@ -0,0 +1,94 @@
1
+ import getFloatedTargetPos from '../helpers/getFloatedTargetPos'
2
+ import toPixel from '../helpers/toPixel'
3
+ import supportDom from '../helpers/supportDom'
4
+
5
+ const TOOLTIP_PLACEMENTS = ['top', 'bottom', 'left', 'right']
6
+
7
+ @supportDom
8
+ export default class Tooltip {
9
+
10
+ constructor(dom) {
11
+ this.dom = dom
12
+ this.tooltip = document.querySelector('[data-global-tooltip]')
13
+ this.init()
14
+ }
15
+
16
+ init() {
17
+ this.appendTooltip()
18
+ this.addEvents()
19
+ }
20
+
21
+ appendTooltip() {
22
+ if (this.tooltip) {
23
+ return
24
+ }
25
+ const tooltip = document.createElement('div')
26
+ tooltip.setAttribute('data-global-tooltip', '')
27
+ tooltip.classList.add('tooltip')
28
+ document.body.appendChild(tooltip)
29
+ this.tooltip = tooltip
30
+ }
31
+
32
+ static remove() {
33
+ const div = document.querySelector('[data-global-tooltip]')
34
+ if (div) {
35
+ div.remove()
36
+ }
37
+ }
38
+
39
+ getPlace() {
40
+ const str = this.dom.dataset.place
41
+ return TOOLTIP_PLACEMENTS.includes(str) ? str : 'bottom'
42
+ }
43
+
44
+ getOffset() {
45
+ const num = parseInt(this.dom.dataset.offset, 10)
46
+ return Number.isInteger(num) ? num : 10
47
+ }
48
+
49
+ setTooltipMsg() {
50
+ const { msg } = this.dom.dataset
51
+ if (this.tooltip.innerHTML !== msg) {
52
+ this.tooltip.innerHTML = msg
53
+ }
54
+ }
55
+
56
+ hide() {
57
+ const { tooltip } = this
58
+ if (tooltip) {
59
+ tooltip.style.opacity = 0
60
+ tooltip.style.display = 'none'
61
+ }
62
+ }
63
+
64
+ addEvents() {
65
+ const { dom, tooltip } = this
66
+ if ('onmouseover' in dom) {
67
+ this.addEvent(dom, 'mouseover', () => {
68
+ this.setTooltipMsg()
69
+
70
+ tooltip.style.opacity = 0
71
+ tooltip.style.display = 'block'
72
+
73
+ const { pos } = getFloatedTargetPos({
74
+ src: dom,
75
+ target: tooltip,
76
+ place: this.getPlace(),
77
+ offset: this.getOffset()
78
+ })
79
+ tooltip.style.left = toPixel(pos.left)
80
+ tooltip.style.top = toPixel(pos.top)
81
+ tooltip.style.opacity = 1
82
+ })
83
+ }
84
+ if ('onmouseleave' in dom) {
85
+ const handleMouseLeave = () => this.hide()
86
+ this.addEvent(dom, 'click', handleMouseLeave)
87
+ this.addEvent(dom, 'mouseleave', handleMouseLeave)
88
+ }
89
+ }
90
+
91
+ destroy() {
92
+ this.hide()
93
+ }
94
+ }
@@ -0,0 +1 @@
1
+ export default []
@@ -0,0 +1,5 @@
1
+ import locale from 'date-fns/locale/zh-TW'
2
+
3
+ export const DEFAULT_TIMEZONE = 'Asia/Taipei'
4
+
5
+ export const DEFAULT_LOCALE = locale
@@ -0,0 +1,53 @@
1
+ import Alert from '../components/Alert'
2
+ import Checkbox from '../components/Checkbox'
3
+ import Dropdown from '../components/Dropdown'
4
+ import Menu from '../components/Menu'
5
+ import Navbar from '../components/Navbar'
6
+ import Radio from '../components/Radio'
7
+ import Sidebar from '../components/Sidebar'
8
+ import Tabbox from '../components/Tabbox'
9
+ import Tooltip from '../components/Tooltip'
10
+
11
+ const $ = selector => Array.from(document.querySelectorAll(selector))
12
+
13
+ const defaultOptions = {
14
+ selectors: {
15
+ alert: '[data-alert]',
16
+ checkbox: 'input[type="checkbox"]',
17
+ dropdown: '[data-dropdown]',
18
+ menu: '[data-menu-toggle]',
19
+ navbar: '[data-navbar]',
20
+ radio: 'input[type="radio"]',
21
+ sidebar: '[data-sidebar-opener]',
22
+ tabbox: '[data-tabbox]',
23
+ tooltip: '[data-tooltip]'
24
+ }
25
+ }
26
+
27
+ export default function bind(opts = {}) {
28
+
29
+ const options = Object.assign({}, defaultOptions, opts)
30
+ const { selectors } = options
31
+
32
+ const alerts = $(selectors.alert).map(dom => new Alert(dom))
33
+ const checkboxes = $(selectors.checkbox).map(dom => new Checkbox(dom))
34
+ const dropdowns = $(selectors.dropdown).map(dom => new Dropdown(dom))
35
+ const menus = $(selectors.menu).map(dom => new Menu(dom))
36
+ const navbars = $(selectors.navbar).map(dom => new Navbar(dom))
37
+ const radios = $(selectors.radio).map(dom => new Radio(dom))
38
+ const sidebars = $(selectors.sidebar).map(dom => new Sidebar(dom))
39
+ const tabboxes = $(selectors.tabbox).map(dom => new Tabbox(dom))
40
+ const tooltips = $(selectors.tooltip).map(dom => new Tooltip(dom))
41
+
42
+ return function unbind() {
43
+ alerts.forEach(alert => alert.destroy())
44
+ checkboxes.forEach(checkbox => checkbox.destroy())
45
+ dropdowns.forEach(dropdown => dropdown.destroy())
46
+ menus.forEach(menu => menu.destroy())
47
+ navbars.forEach(navbar => navbar.destroy())
48
+ radios.forEach(radio => radio.destroy())
49
+ sidebars.forEach(sidebar => sidebar.destroy())
50
+ tabboxes.forEach(tabbox => tabbox.destroy())
51
+ tooltips.forEach(tooltip => tooltip.destroy())
52
+ }
53
+ }
@@ -0,0 +1,5 @@
1
+ import compareAsc from 'date-fns/compareAsc'
2
+
3
+ export default function dateEq(date1, date2) {
4
+ return compareAsc(date1, date2) === 0
5
+ }
@@ -0,0 +1,5 @@
1
+ import compareAsc from 'date-fns/compareAsc'
2
+
3
+ export default function dateLt(date1, date2) {
4
+ return compareAsc(date1, date2) === 1
5
+ }
@@ -0,0 +1,5 @@
1
+ import compareAsc from 'date-fns/compareAsc'
2
+
3
+ export default function dateLt(date1, date2) {
4
+ return compareAsc(date1, date2) === -1
5
+ }
@@ -0,0 +1,10 @@
1
+ export default function docReady() {
2
+ return new Promise(resolve => {
3
+ const { readyState } = document
4
+ if (['complete', 'interactive'].includes(readyState)) {
5
+ setTimeout(resolve, 1)
6
+ return
7
+ }
8
+ document.addEventListener('DOMContentLoaded', resolve)
9
+ })
10
+ }
@@ -0,0 +1,250 @@
1
+ import getDomPos from '@superlanding/getdompos'
2
+ import getScrollTop from '@superlanding/getscrolltop'
3
+ import getScrollLeft from '@superlanding/getscrollleft'
4
+
5
+ // Calculate floated target position for tooltip and dropdown
6
+ export default function getFloatedTargetPos(options) {
7
+
8
+ const { src, target, place, align, offset = 0, offsetLeft, offsetTop } = options
9
+
10
+ const { x: x1, y: y1 } = getDomPos(src)
11
+
12
+ const w1 = src.offsetWidth
13
+ const h1 = src.offsetHeight
14
+
15
+ const w2 = target.offsetWidth
16
+ const h2 = target.offsetHeight
17
+
18
+ let pos = getPos({ x1, y1, w1, h1, w2, h2, place, align, offset })
19
+ let posWithOffsets = addExtraOffsets({ pos, offsetLeft, offsetTop })
20
+
21
+ // auto detect the best placement and alignment
22
+ const detectedPlace = detectPlace({ pos: posWithOffsets, place, w2, h2 })
23
+ const detectedAlign = detectAlign({ pos: posWithOffsets, place, align, w2, h2 })
24
+
25
+ const placeDifferent = (place !== detectedPlace)
26
+ const alignDifferent = (align !== detectedAlign)
27
+
28
+ if (placeDifferent || alignDifferent) {
29
+ pos = getPos({
30
+ x1, y1, w1, h1, w2, h2,
31
+ place: detectedPlace, align: detectedAlign, offset
32
+ })
33
+
34
+ let adjustedOffsetLeft = offsetLeft
35
+ let adjustedOffsetTop = offsetTop
36
+
37
+ if (placeDifferent && ['left', 'right'].includes(detectedPlace)) {
38
+ adjustedOffsetLeft = -adjustedOffsetLeft
39
+ }
40
+ if (placeDifferent && ['top', 'bottom'].includes(detectedPlace)) {
41
+ adjustedOffsetTop = -adjustedOffsetTop
42
+ }
43
+
44
+ posWithOffsets = addExtraOffsets({
45
+ pos,
46
+ offsetLeft: adjustedOffsetLeft,
47
+ offsetTop: adjustedOffsetTop
48
+ })
49
+ }
50
+
51
+ const posWithSafeBoundary = adjustToBoundary({
52
+ pos: posWithOffsets,
53
+ w1, h1, w2, h2,
54
+ place, align
55
+ })
56
+ return {
57
+ pos: posWithSafeBoundary,
58
+ place: detectedPlace,
59
+ align: detectedAlign
60
+ }
61
+ }
62
+
63
+ function getTouchedData({ pos, w2, h2 }) {
64
+ const { left, top } = pos
65
+ const scrollTop = getScrollTop()
66
+ const scrollBottom = scrollTop + window.innerHeight
67
+ const scrollLeft = getScrollLeft()
68
+ const scrollRight = scrollLeft + window.innerWidth
69
+ const touchedTop = (top < scrollTop)
70
+ const touchedBottom = ((top + h2) > scrollBottom)
71
+ const touchedLeft = (left < scrollLeft)
72
+ const touchedRight = ((left + w2) > scrollRight)
73
+ return { touchedTop, touchedBottom, touchedLeft, touchedRight }
74
+ }
75
+
76
+ function detectPlace({ pos, place, w2, h2 }) {
77
+
78
+ const { touchedTop, touchedBottom,
79
+ touchedLeft, touchedRight } = getTouchedData({ pos, w2, h2 })
80
+
81
+ if ((place === 'top') && touchedTop) {
82
+ return 'bottom'
83
+ }
84
+ if ((place === 'bottom') && touchedBottom) {
85
+ return 'top'
86
+ }
87
+ if ((place === 'left') && touchedLeft) {
88
+ return 'right'
89
+ }
90
+ if ((place === 'right') && touchedRight) {
91
+ return 'left'
92
+ }
93
+ return place
94
+ }
95
+
96
+ function detectAlign({ pos, place, align, w2, h2 }) {
97
+ const isVertical = ['top', 'bottom'].includes(place)
98
+ const isHorizontal = ['left', 'right'].includes(place)
99
+ const { touchedTop, touchedBottom,
100
+ touchedLeft, touchedRight } = getTouchedData({ pos, w2, h2 })
101
+
102
+ if (isVertical && touchedLeft) {
103
+ return 'left'
104
+ }
105
+ if (isVertical && touchedRight) {
106
+ return 'right'
107
+ }
108
+ if (isHorizontal && touchedTop) {
109
+ return 'top'
110
+ }
111
+ if (isHorizontal && touchedBottom) {
112
+ return 'bottom'
113
+ }
114
+ return align
115
+ }
116
+
117
+ function getPos(options) {
118
+
119
+ const { place, align = 'center' } = options
120
+
121
+ switch (`${place}_${align}`) {
122
+ case 'top_left':
123
+ return getTopLeftPos(options)
124
+ case 'top_right':
125
+ return getTopRightPos(options)
126
+ case 'top_center':
127
+ return getTopCenterPos(options)
128
+ case 'bottom_left':
129
+ return getBottomLeftPos(options)
130
+ case 'bottom_right':
131
+ return getBottomRightPos(options)
132
+ case 'bottom_center':
133
+ return getBottomCenterPos(options)
134
+ case 'left_top':
135
+ return getLeftTopPos(options)
136
+ case 'left_bottom':
137
+ return getLeftBottomPos(options)
138
+ case 'left_center':
139
+ return getLeftCenterPos(options)
140
+ case 'right_top':
141
+ return getRightTopPos(options)
142
+ case 'right_bottom':
143
+ return getRightBottomPos(options)
144
+ case 'right_center':
145
+ return getRightCenterPos(options)
146
+ default:
147
+ throw new Error(`Unsupported placement and alignment: ${place} ${align}`)
148
+ }
149
+ }
150
+
151
+ function getTopLeftPos({ x1, y1, h2, offset }) {
152
+ const top = y1 - offset - h2
153
+ const left = x1
154
+ return { left, top }
155
+ }
156
+
157
+ function getTopRightPos({ x1, y1, w1, w2, h2, offset }) {
158
+ const top = y1 - offset - h2
159
+ const left = x1 - (w2 - w1)
160
+ return { left, top }
161
+ }
162
+
163
+ function getTopCenterPos({ x1, y1, w1, w2, h2, offset }) {
164
+ const top = y1 - offset - h2
165
+ const left = x1 + (w1 / 2) - (w2 / 2)
166
+ return { left, top }
167
+ }
168
+
169
+ function getBottomLeftPos({ x1, y1, h1, offset }) {
170
+ const top = y1 + h1 + offset
171
+ const left = x1
172
+ return { left, top }
173
+ }
174
+
175
+ function getBottomRightPos({ x1, y1, w1, h1, w2, offset }) {
176
+ const top = y1 + h1 + offset
177
+ const left = x1 - (w2 - w1)
178
+ return { left, top }
179
+ }
180
+
181
+ function getBottomCenterPos({ x1, y1, w1, h1, w2, offset }) {
182
+ const top = y1 + h1 + offset
183
+ const left = x1 + (w1 / 2) - (w2 / 2)
184
+ return { left, top }
185
+ }
186
+
187
+ function getLeftTopPos({ x1, y1, w2, offset }) {
188
+ const left = x1 - offset - w2
189
+ const top = y1
190
+ return { left, top }
191
+ }
192
+
193
+ function getLeftBottomPos({ x1, y1, h1, w2, h2, offset }) {
194
+ const left = x1 - offset - w2
195
+ const top = y1 - (h2 - h1)
196
+ return { left, top }
197
+ }
198
+
199
+ function getLeftCenterPos({ x1, y1, h1, w2, h2, offset }) {
200
+ const left = x1 - offset - w2
201
+ const top = y1 + (h1 / 2) - (h2 / 2)
202
+ return { left, top }
203
+ }
204
+
205
+ function getRightTopPos({ x1, y1, w1, offset }) {
206
+ const left = x1 + w1 + offset
207
+ const top = y1
208
+ return { left, top }
209
+ }
210
+
211
+ function getRightBottomPos({ x1, y1, w1, h1, h2, offset }) {
212
+ const left = x1 + w1 + offset
213
+ const top = y1 - (h2 - h1)
214
+ return { left, top }
215
+ }
216
+
217
+ function getRightCenterPos({ x1, y1, w1, h1, h2, offset }) {
218
+ const left = x1 + w1 + offset
219
+ const top = y1 + (h1 / 2) - (h2 / 2)
220
+ return { left, top }
221
+ }
222
+
223
+ function adjustToBoundary({ pos, w1, w2, h1, h2 }) {
224
+
225
+ const { touchedTop, touchedBottom,
226
+ touchedLeft, touchedRight } = getTouchedData({ pos, w2, h2 })
227
+
228
+ let left = pos.left
229
+ let top = pos.top
230
+ if (touchedLeft) {
231
+ left = 0
232
+ }
233
+ if (touchedRight) {
234
+ left = window.innerWidth - w2 + w1;
235
+ }
236
+ if (touchedTop) {
237
+ top = 0
238
+ }
239
+ if (touchedBottom) {
240
+ top = window.innerHeight - h2 + h1
241
+ }
242
+ return { top, left }
243
+ }
244
+
245
+ function addExtraOffsets({ pos, offsetLeft = 0, offsetTop = 0 }) {
246
+ return {
247
+ left: pos.left + offsetLeft,
248
+ top: pos.top + offsetTop
249
+ }
250
+ }