beyond-rails 0.0.188 → 0.0.193

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/src/js/components/Alert.js +1 -1
  3. data/src/js/components/Autocomplete.js +1 -1
  4. data/src/js/components/AutocompleteMenu.js +1 -1
  5. data/src/js/components/BarChart.js +452 -0
  6. data/src/js/components/Btn.js +1 -1
  7. data/src/js/components/Checkbox.js +1 -1
  8. data/src/js/components/DateInput.js +1 -1
  9. data/src/js/components/DateMenu.js +1 -1
  10. data/src/js/components/DateTimeRanger.js +1 -1
  11. data/src/js/components/Datepicker.js +1 -1
  12. data/src/js/components/DatepickerBtnArrow.js +1 -1
  13. data/src/js/components/Dropdown.js +1 -1
  14. data/src/js/components/LineChart.js +535 -0
  15. data/src/js/components/Menu.js +1 -1
  16. data/src/js/components/Modal.js +76 -31
  17. data/src/js/components/Navbar.js +1 -1
  18. data/src/js/components/Radio.js +1 -1
  19. data/src/js/components/SearchDropdown.js +1 -1
  20. data/src/js/components/Sidebar.js +1 -1
  21. data/src/js/components/Tabbox.js +1 -1
  22. data/src/js/components/TimeInput.js +1 -1
  23. data/src/js/components/TimeMenu.js +1 -1
  24. data/src/js/components/Timepicker.js +1 -1
  25. data/src/js/components/Toast.js +1 -1
  26. data/src/js/components/ToastItem.js +1 -1
  27. data/src/js/components/Tooltip.js +1 -1
  28. data/src/js/decorators/chartCommon.js +218 -0
  29. data/src/js/{utils → decorators}/supportDom.js +1 -1
  30. data/src/js/index.js +6 -2
  31. data/src/js/jquery/bindModalFn.js +57 -6
  32. data/src/js/utils/index.js +10 -1
  33. data/src/js/utils/isDef.js +3 -0
  34. data/src/js/utils/isInt.js +3 -0
  35. data/src/js/utils/isUndef.js +3 -0
  36. data/src/sass/_beyond.scss +1 -0
  37. data/src/sass/components/_breadcrumb.scss +4 -4
  38. data/src/sass/components/_chart.scss +14 -0
  39. data/src/sass/components/_mega-menu.scss +22 -28
  40. data/src/sass/components/_nav.scss +1 -0
  41. metadata +28 -9
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
 
3
3
  @supportDom
4
4
  export default class Menu {
@@ -1,6 +1,8 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
  import { noop } from '../utils'
3
3
 
4
+ let globalModalId = 0
5
+
4
6
  @supportDom
5
7
  export default class Modal {
6
8
 
@@ -15,19 +17,41 @@ export default class Modal {
15
17
  }
16
18
 
17
19
  init() {
18
- this.modalId = this.dom.dataset.modalOpener
19
- const selector = `[data-modal="${this.modalId}"]`
20
- this.modal = document.querySelector(selector)
21
- if (! this.modal) {
22
- throw new Error(`${selector} is not defined.`)
23
- }
20
+ this.bindEvents()
21
+ }
22
+
23
+ bindEvents() {
24
+ this.setModalDom()
24
25
  this.closeBtn = this.modal.querySelector('[data-close]')
25
26
  this.cancelBtn = this.modal.querySelector('[data-cancel]')
26
27
  this.confirmBtn = this.modal.querySelector('[data-confirm]')
27
28
  this.addEvents()
28
29
  }
29
30
 
30
- show() {
31
+ setModalDom() {
32
+ const { modalOpener, modal } = this.dom.dataset
33
+
34
+ if (modalOpener) {
35
+ this.modalId = this.dom.dataset.modalOpener
36
+ const selector = `[data-modal="${this.modalId}"]`
37
+ this.modal = document.querySelector(selector)
38
+ return
39
+ }
40
+
41
+ if (modal) {
42
+ this.modalId = modal
43
+ }
44
+ else {
45
+ this.modalId = `modal-${++globalModalId}`
46
+ this.dom.dataset.modal = this.modalId
47
+ }
48
+ this.modal = this.dom
49
+ }
50
+
51
+ show(html) {
52
+ if (html) {
53
+ this.replace(html)
54
+ }
31
55
  this.isVisible = true
32
56
  this.modal.style.display = 'block'
33
57
  setTimeout(() => {
@@ -43,24 +67,47 @@ export default class Modal {
43
67
  }, 300)
44
68
  }
45
69
 
46
- addEvents() {
47
- this.addEvent(this.dom, 'click', () => this.show())
70
+ replace(html) {
71
+ this.destroy()
72
+ this.modalId = null
48
73
 
49
- if (this.closeBtn) {
50
- this.addEvent(this.closeBtn, 'click', () => {
51
- this.hide()
52
- this.options.cancel('close')
53
- })
74
+ // replace with new dom
75
+ const div = document.createElement('div')
76
+ div.innerHTML = html.trim()
77
+ const dom = div.firstChild
78
+ this.dom.parentNode.replaceChild(dom, this.dom)
79
+
80
+ this.dom = dom
81
+ this.dom._modal = this
82
+ this.init()
83
+ }
84
+
85
+ visible() {
86
+ return this.isVisible
87
+ }
88
+
89
+ addEventIfDomExists(dom, event, cb) {
90
+ if (dom) {
91
+ this.addEvent(dom, event, cb)
54
92
  }
93
+ }
55
94
 
56
- if (this.cancelBtn) {
57
- this.addEvent(this.cancelBtn, 'click', () => {
58
- this.hide()
59
- this.options.cancel('cancel')
60
- })
95
+ addEvents() {
96
+ if (this.dom.dataset.modalOpener) {
97
+ this.addEventIfDomExists(this.dom, 'click', () => this.show())
61
98
  }
62
99
 
63
- this.addEvent(this.modal, 'click', event => {
100
+ this.addEventIfDomExists(this.closeBtn, 'click', () => {
101
+ this.hide()
102
+ this.options.cancel('close')
103
+ })
104
+
105
+ this.addEventIfDomExists(this.cancelBtn, 'click', () => {
106
+ this.hide()
107
+ this.options.cancel('cancel')
108
+ })
109
+
110
+ this.addEventIfDomExists(this.modal, 'click', event => {
64
111
  // is backdrop
65
112
  if (event.target.dataset.modal === this.modalId) {
66
113
  this.hide()
@@ -68,15 +115,13 @@ export default class Modal {
68
115
  }
69
116
  })
70
117
 
71
- if (this.confirmBtn) {
72
- this.addEvent(this.confirmBtn, 'click', () => {
73
- if (typeof this.options.confirm === 'function') {
74
- this.options.confirm()
75
- }
76
- else {
77
- this.hide()
78
- }
79
- })
80
- }
118
+ this.addEventIfDomExists(this.confirmBtn, 'click', () => {
119
+ if (typeof this.options.confirm === 'function') {
120
+ this.options.confirm()
121
+ }
122
+ else {
123
+ this.hide()
124
+ }
125
+ })
81
126
  }
82
127
  }
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
 
3
3
  @supportDom
4
4
  export default class Navbar {
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
 
3
3
  @supportDom
4
4
  export default class Radio {
@@ -1,5 +1,5 @@
1
1
  import getFloatedTargetPos from '../utils/getFloatedTargetPos'
2
- import supportDom from '../utils/supportDom'
2
+ import supportDom from '../decorators/supportDom'
3
3
  import getKey from '../utils/getKey'
4
4
  import { debounce, noop, toPixel, throttle } from '../utils'
5
5
 
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
 
3
3
  @supportDom
4
4
  export default class Sidebar {
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
  import Dropdown from './Dropdown'
3
3
  import { noop } from '../utils'
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { DEFAULT_TIMEZONE } from '../consts'
2
- import supportDom from '../utils/supportDom'
2
+ import supportDom from '../decorators/supportDom'
3
3
  import isTouchDevice from '../utils/isTouchDevice'
4
4
  import { format } from '../utils'
5
5
 
@@ -1,5 +1,5 @@
1
1
  import getFloatedTargetPos from '../utils/getFloatedTargetPos'
2
- import supportDom from '../utils/supportDom'
2
+ import supportDom from '../decorators/supportDom'
3
3
  import { getHours, getMinutes, range, toPixel } from '../utils'
4
4
 
5
5
  @supportDom
@@ -1,7 +1,7 @@
1
1
  import TimeInput from './TimeInput'
2
2
  import TimeMenu from './TimeMenu'
3
3
  import { DEFAULT_TIMEZONE } from '../consts'
4
- import supportDom from '../utils/supportDom'
4
+ import supportDom from '../decorators/supportDom'
5
5
  import {
6
6
  dateToTimestamp,
7
7
  noop,
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
  import ToastItem from './ToastItem'
3
3
 
4
4
  @supportDom
@@ -1,4 +1,4 @@
1
- import supportDom from '../utils/supportDom'
1
+ import supportDom from '../decorators/supportDom'
2
2
 
3
3
  @supportDom
4
4
  export default class ToastItem {
@@ -1,5 +1,5 @@
1
1
  import getFloatedTargetPos from '../utils/getFloatedTargetPos'
2
- import supportDom from '../utils/supportDom'
2
+ import supportDom from '../decorators/supportDom'
3
3
  import { toPixel } from '../utils'
4
4
 
5
5
  const TOOLTIP_PLACEMENTS = ['top', 'bottom', 'left', 'right']
@@ -0,0 +1,218 @@
1
+ import isDef from '../utils/isDef'
2
+ import isUndef from '../utils/isUndef'
3
+ import { getDomPos, range, toPixel, isFunction } from '../utils'
4
+
5
+ export default function chartCommon(target) {
6
+
7
+ return class extends target {
8
+
9
+ init() {
10
+ this.layers = []
11
+ if (isFunction(super.init)) {
12
+ super.init()
13
+ }
14
+ }
15
+
16
+ get firstLayer() {
17
+ return this.layers[0]
18
+ }
19
+
20
+ addLayer() {
21
+ const { dom } = this
22
+ const canvas = document.createElement('canvas')
23
+ canvas.style.position = 'absolute'
24
+ canvas.style.top = 0
25
+ canvas.style.left = 0
26
+ canvas.style.right = 0
27
+ canvas.style.bottom = 0
28
+ const ctx = canvas.getContext('2d')
29
+
30
+ this.setCanvasSize(canvas)
31
+ this.layers.push({ canvas, ctx })
32
+
33
+ dom.style.position = 'relative'
34
+ dom.appendChild(canvas)
35
+ }
36
+
37
+ bindMedia() {
38
+ if (this.media) {
39
+ return
40
+ }
41
+ this.media = window.matchMedia(`(resolution: ${this.dpr}dppx)`)
42
+ this._handleDprChange = this.handleDprChange.bind(this)
43
+ this.media.addListener(this._handleDprChange)
44
+ }
45
+
46
+ clear() {
47
+ const { ctx } = this
48
+ ctx.fillStyle = this.bgColor
49
+ ctx.fillRect(0, 0, this.width, this.height)
50
+ }
51
+
52
+ fillCircle(ctx, x, y, radius, style, alpha) {
53
+ ctx.save()
54
+ ctx.beginPath()
55
+ ctx.arc(x, y, radius, 0, 2 * Math.PI)
56
+ ctx.fillStyle = style
57
+ ctx.globalAlpha = alpha || 1
58
+ ctx.fill()
59
+ ctx.closePath()
60
+ ctx.restore()
61
+ }
62
+
63
+ getAutoStep(firstValue, lastValue, pointsLength) {
64
+ return (lastValue - firstValue) / (pointsLength - 1)
65
+ }
66
+
67
+ getHighestCanvas() {
68
+ const { layers, canvas } = this
69
+ if (layers.length === 0) {
70
+ return canvas
71
+ }
72
+ return layers[layers.length - 1].canvas
73
+ }
74
+
75
+ // real position in window including scrolling distance
76
+ getMousePos(canvasMousePos) {
77
+ const domPos = getDomPos(this.dom)
78
+ return {
79
+ x: domPos.x + canvasMousePos.x,
80
+ y: domPos.y + canvasMousePos.y
81
+ }
82
+ }
83
+
84
+ getMousePosInCanvas(event) {
85
+ const rect = this.canvas.getBoundingClientRect()
86
+ return {
87
+ x: event.clientX - rect.left,
88
+ y: event.clientY - rect.top
89
+ }
90
+ }
91
+
92
+ getLengthTotalData(gap, gutter, values, measureLength, toLabel) {
93
+
94
+ const valueCount = values.length
95
+ const marked = {}
96
+
97
+ // mark the first and last
98
+ marked[0] = true
99
+ marked[valueCount - 1] = true
100
+
101
+ // Check whether a value can be marked next
102
+ // For example, gap is 2
103
+ //
104
+ // values: 1 2 3 4 5 6 7
105
+ // marked: v v
106
+ //
107
+ // 4 will only be marked because it has enough gap on left and right side.
108
+ const hasGap = index => {
109
+ return range(index - gap, index).every(i => isUndef(marked[i])) &&
110
+ range(index + 1, index + gap + 1).every(i => isUndef(marked[i]))
111
+ }
112
+
113
+ return values.reduce((res, value, i) => {
114
+
115
+ if (i === 0) {
116
+ const label = toLabel(value)
117
+ const length = measureLength(label)
118
+ const lengthTotal = res.lengthTotal + length + gutter
119
+ const rows = res.rows.slice()
120
+ rows.push({ label, length, value })
121
+ return { lengthTotal, rows }
122
+ }
123
+ if (i === (valueCount - 1)) {
124
+ const label = toLabel(value)
125
+ const length = measureLength(label)
126
+ const lengthTotal = res.lengthTotal + length
127
+ const rows = res.rows.slice()
128
+ rows.push({ label, length, value })
129
+ return { lengthTotal, rows }
130
+ }
131
+ if (hasGap(i)) {
132
+ const label = toLabel(value)
133
+ marked[i] = true
134
+ const length = measureLength(label)
135
+ const lengthTotal = res.lengthTotal + length + gutter
136
+ const rows = res.rows.slice()
137
+ rows.push({ label, length, value })
138
+ return { lengthTotal, rows }
139
+ }
140
+ return res
141
+ }, {
142
+ lengthTotal: 0,
143
+ rows: []
144
+ })
145
+ }
146
+
147
+ getStepStartEnd(step, firstValue, lastValue) {
148
+
149
+ const stepStart = parseInt(firstValue / step, 10) * step
150
+ let stepEnd = parseInt(lastValue / step, 10) * step
151
+
152
+ if (stepEnd < lastValue) {
153
+ stepEnd += step
154
+ }
155
+ return [stepStart, stepEnd]
156
+ }
157
+
158
+ raf(fn) {
159
+ if (isDef(window.requestAnimationFrame)) {
160
+ return window.requestAnimationFrame(fn)
161
+ }
162
+ return fn()
163
+ }
164
+
165
+ removeAllLayers() {
166
+ const { dom } = this
167
+ this.layers.forEach(layer => {
168
+ const { canvas } = layer
169
+ if (dom.contains(canvas)) {
170
+ dom.removeChild(canvas)
171
+ }
172
+ })
173
+ }
174
+
175
+ setCanvas() {
176
+ const canvas = document.createElement('canvas')
177
+ const ctx = canvas.getContext('2d')
178
+
179
+ this.canvas = canvas
180
+ this.ctx = ctx
181
+ this.setCanvasFontSize(this.canvas, this.fontSize)
182
+ this.setCanvasSize(canvas)
183
+
184
+ this.dom.appendChild(canvas)
185
+ }
186
+
187
+ setCanvasFontSize(canvas, fontSize) {
188
+ const ctx = canvas.getContext('2d')
189
+ const args = ctx.font.split(' ')
190
+ ctx.font = fontSize + 'px ' + args[args.length - 1]
191
+ }
192
+
193
+ setCanvasSize(canvas) {
194
+ const { dpr, width, height } = this
195
+
196
+ // https://coderwall.com/p/vmkk6a/how-to-make-the-canvas-not-look-like-crap-on-retina
197
+ canvas.width = width * dpr
198
+ canvas.height = height * dpr
199
+ canvas.style.width = toPixel(width)
200
+ canvas.style.height = toPixel(height)
201
+ canvas.getContext('2d').scale(dpr, dpr)
202
+ }
203
+
204
+ setDomWidthIfNeeded() {
205
+ if (isUndef(this.options.width)) {
206
+ this.width = this.dom.offsetWidth
207
+ }
208
+ }
209
+
210
+ setDpr() {
211
+ this.dpr = window.devicePixelRatio || 1
212
+ }
213
+
214
+ unbindMedia() {
215
+ this.media.removeListener(this._handleDprChange)
216
+ }
217
+ }
218
+ }