beyond-rails 0.0.189 → 0.0.194
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/src/js/components/Alert.js +1 -1
- data/src/js/components/Autocomplete.js +1 -1
- data/src/js/components/AutocompleteMenu.js +1 -1
- data/src/js/components/BarChart.js +452 -0
- data/src/js/components/Btn.js +1 -1
- data/src/js/components/Checkbox.js +1 -1
- data/src/js/components/DateInput.js +1 -1
- data/src/js/components/DateMenu.js +1 -1
- data/src/js/components/DateTimeRanger.js +1 -1
- data/src/js/components/Datepicker.js +1 -1
- data/src/js/components/DatepickerBtnArrow.js +1 -1
- data/src/js/components/Dropdown.js +1 -1
- data/src/js/components/LineChart.js +553 -0
- data/src/js/components/Menu.js +1 -1
- data/src/js/components/Modal.js +1 -1
- data/src/js/components/Navbar.js +1 -1
- data/src/js/components/Radio.js +1 -1
- data/src/js/components/SearchDropdown.js +1 -1
- data/src/js/components/Sidebar.js +1 -1
- data/src/js/components/Tabbox.js +1 -1
- data/src/js/components/TimeInput.js +1 -1
- data/src/js/components/TimeMenu.js +1 -1
- data/src/js/components/Timepicker.js +1 -1
- data/src/js/components/Toast.js +1 -1
- data/src/js/components/ToastItem.js +1 -1
- data/src/js/components/Tooltip.js +1 -1
- data/src/js/decorators/chartCommon.js +222 -0
- data/src/js/{utils → decorators}/supportDom.js +1 -1
- data/src/js/index.js +6 -2
- data/src/js/utils/index.js +10 -1
- data/src/js/utils/isDef.js +3 -0
- data/src/js/utils/isInt.js +3 -0
- data/src/js/utils/isUndef.js +3 -0
- data/src/sass/_beyond.scss +1 -0
- data/src/sass/components/_breadcrumb.scss +4 -7
- data/src/sass/components/_chart.scss +14 -0
- metadata +10 -3
data/src/js/components/Menu.js
CHANGED
data/src/js/components/Modal.js
CHANGED
data/src/js/components/Navbar.js
CHANGED
data/src/js/components/Radio.js
CHANGED
data/src/js/components/Tabbox.js
CHANGED
data/src/js/components/Toast.js
CHANGED
@@ -0,0 +1,222 @@
|
|
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
|
+
measureWidth(value) {
|
159
|
+
return this.ctx.measureText(value).width
|
160
|
+
}
|
161
|
+
|
162
|
+
raf(fn) {
|
163
|
+
if (isDef(window.requestAnimationFrame)) {
|
164
|
+
return window.requestAnimationFrame(fn)
|
165
|
+
}
|
166
|
+
return fn()
|
167
|
+
}
|
168
|
+
|
169
|
+
removeAllLayers() {
|
170
|
+
const { dom } = this
|
171
|
+
this.layers.forEach(layer => {
|
172
|
+
const { canvas } = layer
|
173
|
+
if (dom.contains(canvas)) {
|
174
|
+
dom.removeChild(canvas)
|
175
|
+
}
|
176
|
+
})
|
177
|
+
}
|
178
|
+
|
179
|
+
setCanvas() {
|
180
|
+
const canvas = document.createElement('canvas')
|
181
|
+
const ctx = canvas.getContext('2d')
|
182
|
+
|
183
|
+
this.canvas = canvas
|
184
|
+
this.ctx = ctx
|
185
|
+
this.setCanvasFontSize(this.canvas, this.fontSize)
|
186
|
+
this.setCanvasSize(canvas)
|
187
|
+
|
188
|
+
this.dom.appendChild(canvas)
|
189
|
+
}
|
190
|
+
|
191
|
+
setCanvasFontSize(canvas, fontSize) {
|
192
|
+
const ctx = canvas.getContext('2d')
|
193
|
+
const args = ctx.font.split(' ')
|
194
|
+
ctx.font = fontSize + 'px ' + args[args.length - 1]
|
195
|
+
}
|
196
|
+
|
197
|
+
setCanvasSize(canvas) {
|
198
|
+
const { dpr, width, height } = this
|
199
|
+
|
200
|
+
// https://coderwall.com/p/vmkk6a/how-to-make-the-canvas-not-look-like-crap-on-retina
|
201
|
+
canvas.width = width * dpr
|
202
|
+
canvas.height = height * dpr
|
203
|
+
canvas.style.width = toPixel(width)
|
204
|
+
canvas.style.height = toPixel(height)
|
205
|
+
canvas.getContext('2d').scale(dpr, dpr)
|
206
|
+
}
|
207
|
+
|
208
|
+
setDomWidthIfNeeded() {
|
209
|
+
if (isUndef(this.options.width)) {
|
210
|
+
this.width = this.dom.offsetWidth
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
setDpr() {
|
215
|
+
this.dpr = window.devicePixelRatio || 1
|
216
|
+
}
|
217
|
+
|
218
|
+
unbindMedia() {
|
219
|
+
this.media.removeListener(this._handleDprChange)
|
220
|
+
}
|
221
|
+
}
|
222
|
+
}
|
data/src/js/index.js
CHANGED
@@ -6,19 +6,21 @@ import './polyfills/nodeRemove'
|
|
6
6
|
import './polyfills/elementDataset'
|
7
7
|
import Alert from './components/Alert'
|
8
8
|
import Autocomplete from './components/Autocomplete'
|
9
|
+
import BarChart from './components/BarChart'
|
9
10
|
import Btn from './components/Btn'
|
10
11
|
import Checkbox from './components/Checkbox'
|
11
12
|
import DateTimeRanger from './components/DateTimeRanger'
|
12
13
|
import Datepicker from './components/Datepicker'
|
13
14
|
import Dropdown from './components/Dropdown'
|
15
|
+
import LineChart from './components/LineChart'
|
14
16
|
import Menu from './components/Menu'
|
15
17
|
import Modal from './components/Modal'
|
16
18
|
import Navbar from './components/Navbar'
|
17
19
|
import Radio from './components/Radio'
|
18
20
|
import SearchDropdown from './components/SearchDropdown'
|
19
21
|
import Sidebar from './components/Sidebar'
|
20
|
-
import Timepicker from './components/Timepicker'
|
21
22
|
import Tabbox from './components/Tabbox'
|
23
|
+
import Timepicker from './components/Timepicker'
|
22
24
|
import Toast from './components/Toast'
|
23
25
|
import Tooltip from './components/Tooltip'
|
24
26
|
import bind from './utils/bind'
|
@@ -28,19 +30,21 @@ import unbindAll from './utils/unbindAll'
|
|
28
30
|
export {
|
29
31
|
Alert,
|
30
32
|
Autocomplete,
|
33
|
+
BarChart,
|
31
34
|
Btn,
|
32
35
|
Checkbox,
|
33
36
|
DateTimeRanger,
|
34
37
|
Datepicker,
|
35
38
|
Dropdown,
|
39
|
+
LineChart,
|
36
40
|
Menu,
|
37
41
|
Modal,
|
38
42
|
Navbar,
|
39
43
|
Radio,
|
40
44
|
SearchDropdown,
|
41
45
|
Sidebar,
|
42
|
-
Timepicker,
|
43
46
|
Tabbox,
|
47
|
+
Timepicker,
|
44
48
|
Toast,
|
45
49
|
Tooltip,
|
46
50
|
bind,
|
data/src/js/utils/index.js
CHANGED
@@ -33,6 +33,10 @@ import isFunction from 'lodash.isfunction'
|
|
33
33
|
import noop from 'lodash.noop'
|
34
34
|
import range from 'lodash.range'
|
35
35
|
import throttle from 'lodash.throttle'
|
36
|
+
import uniqBy from 'lodash.uniqby'
|
37
|
+
import sortBy from 'lodash.sortby'
|
38
|
+
|
39
|
+
import mem from 'mem'
|
36
40
|
|
37
41
|
export {
|
38
42
|
// @superlanding
|
@@ -69,5 +73,10 @@ export {
|
|
69
73
|
isFunction,
|
70
74
|
noop,
|
71
75
|
range,
|
72
|
-
throttle
|
76
|
+
throttle,
|
77
|
+
uniqBy,
|
78
|
+
sortBy,
|
79
|
+
|
80
|
+
// others
|
81
|
+
mem
|
73
82
|
}
|
data/src/sass/_beyond.scss
CHANGED
@@ -4,17 +4,14 @@
|
|
4
4
|
padding: .75rem 1rem;
|
5
5
|
margin-bottom: 1rem;
|
6
6
|
list-style: none;
|
7
|
-
|
7
|
+
li + li::before {
|
8
8
|
display: inline-block;
|
9
9
|
padding-right: .7rem;
|
10
10
|
padding-left: .7rem;
|
11
|
-
color:
|
11
|
+
color: $text-color-strong;
|
12
12
|
content: '/';
|
13
13
|
}
|
14
|
-
|
15
|
-
color:
|
16
|
-
}
|
17
|
-
.breadcrumb-item a {
|
18
|
-
color: #000;
|
14
|
+
li:last-child {
|
15
|
+
color: $text-color-strong;
|
19
16
|
}
|
20
17
|
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
.chart {
|
2
|
+
font-family: Roboto;
|
3
|
+
}
|
4
|
+
|
5
|
+
.chart-menu {
|
6
|
+
display: none;
|
7
|
+
position: absolute;
|
8
|
+
background-color: #fff;
|
9
|
+
padding: 10px 13px;
|
10
|
+
box-shadow: 4px 4px 15px 1px rgba(68, 68, 72, .12);
|
11
|
+
color: #3c4257;
|
12
|
+
z-index: 1;
|
13
|
+
border: 1px solid #e8e8e8;
|
14
|
+
}
|