beyond-rails 0.0.229 → 0.0.230
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/TagInput.js +145 -0
- data/src/js/decorators/chartCommon.js +6 -8
- data/src/js/index.js +2 -0
- data/src/js/utils/getKey.js +1 -0
- data/src/js/utils/isStr.js +3 -0
- data/src/js/utils/raf.js +8 -0
- data/src/sass/_animations.scss +13 -0
- data/src/sass/_beyond.scss +2 -0
- data/src/sass/components/_tag-input.scss +26 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf80575d0a2ac63e76f75b053115cd6c5518382878d406745c4f959d602d2767
|
4
|
+
data.tar.gz: b4c4372056bc1e9d5deddafbf62cadb8ab5ac8f53e3761a36f876b8b4db3897d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6c4b45f205f287d815e16e2b1b9065463a730f66c6e4eb62189165e37b29eede35006033568840aba125af4f0ef79740cab5458095aae0ac7a49935b24d07e8
|
7
|
+
data.tar.gz: ff1f358c7be11d00acfe9756e163be5391188f8d2b7f6581f95aeb1bcc2dc1552be875e63862960be5e3bd97dc225ee4e0535033b908cdef3aab7588defce173
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import raf from '../utils/raf'
|
2
|
+
import isStr from '../utils/isStr'
|
3
|
+
import supportDom from '../decorators/supportDom'
|
4
|
+
import getKey from '../utils/getKey'
|
5
|
+
|
6
|
+
@supportDom
|
7
|
+
export default class TagInput {
|
8
|
+
|
9
|
+
constructor(dom, options = {}) {
|
10
|
+
this.dom = dom
|
11
|
+
this.defaultInputWidth = 128
|
12
|
+
this.validate = options.validate || (() => ({ isTag: true }))
|
13
|
+
this.change = options.change || (() => {})
|
14
|
+
this.isComposing = false
|
15
|
+
this.raf = raf
|
16
|
+
this.tags = []
|
17
|
+
this.init()
|
18
|
+
}
|
19
|
+
|
20
|
+
init() {
|
21
|
+
this.setup()
|
22
|
+
this.addEvents()
|
23
|
+
}
|
24
|
+
|
25
|
+
setup() {
|
26
|
+
const input = document.createElement('input')
|
27
|
+
input.type = 'text'
|
28
|
+
input.style.width = this.defaultInputWidth + 'px'
|
29
|
+
this.input = input
|
30
|
+
this.canvas = document.createElement('canvas')
|
31
|
+
this.dom.append(input)
|
32
|
+
}
|
33
|
+
|
34
|
+
getTextWidth(text, font) {
|
35
|
+
const context = this.canvas.getContext('2d')
|
36
|
+
context.font = font
|
37
|
+
const metrics = context.measureText(text)
|
38
|
+
return metrics.width
|
39
|
+
}
|
40
|
+
|
41
|
+
getNextInputWidth(textWidth) {
|
42
|
+
const { defaultInputWidth } = this
|
43
|
+
// spaces before text and after text
|
44
|
+
const delta = 5
|
45
|
+
const nextWidth = textWidth + delta
|
46
|
+
if (nextWidth < defaultInputWidth) {
|
47
|
+
return defaultInputWidth
|
48
|
+
}
|
49
|
+
return nextWidth
|
50
|
+
}
|
51
|
+
|
52
|
+
shake() {
|
53
|
+
this.dom.classList.add('shake')
|
54
|
+
setTimeout(() => {
|
55
|
+
this.dom.classList.remove('shake')
|
56
|
+
}, 500)
|
57
|
+
}
|
58
|
+
|
59
|
+
async addTagIfNeeded(value) {
|
60
|
+
const { input } = this
|
61
|
+
const inputValue = input.value
|
62
|
+
const res = await this.validate(inputValue)
|
63
|
+
if (! res.isTag) {
|
64
|
+
return this.shake()
|
65
|
+
}
|
66
|
+
const classname = res.classname ? ` ${res.classname}` : ''
|
67
|
+
const tag = document.createElement('div')
|
68
|
+
|
69
|
+
tag.className = 'tag' + classname
|
70
|
+
tag.textContent = inputValue
|
71
|
+
|
72
|
+
const btn = document.createElement('button')
|
73
|
+
btn.type = 'button'
|
74
|
+
|
75
|
+
// https://wesbos.com/times-html-entity-close-button
|
76
|
+
btn.textContent = '×'
|
77
|
+
const handleBtnClick = () => {
|
78
|
+
this.tags = this.tags.filter(row => row.elem !== tag)
|
79
|
+
btn.removeEventListener('click', handleBtnClick)
|
80
|
+
tag.remove()
|
81
|
+
this.change(this.tags.slice())
|
82
|
+
}
|
83
|
+
btn.addEventListener('click', handleBtnClick)
|
84
|
+
tag.appendChild(btn)
|
85
|
+
|
86
|
+
this.tags.push({ elem: tag, remove: handleBtnClick, res })
|
87
|
+
this.dom.insertBefore(tag, input)
|
88
|
+
input.value = ''
|
89
|
+
|
90
|
+
this.change(this.tags.slice())
|
91
|
+
}
|
92
|
+
|
93
|
+
removeTagIfNeeded() {
|
94
|
+
const lastTag = this.tags[this.tags.length - 1]
|
95
|
+
if ((this.input.value === '') && lastTag) {
|
96
|
+
lastTag.remove()
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
addEvents() {
|
101
|
+
const { input } = this
|
102
|
+
const font = window.getComputedStyle(input)
|
103
|
+
.getPropertyValue('font')
|
104
|
+
|
105
|
+
this.addEvent(this.dom, 'click', event => {
|
106
|
+
if (event.target === this.dom) {
|
107
|
+
this.input.focus()
|
108
|
+
}
|
109
|
+
})
|
110
|
+
|
111
|
+
this.addEvent(input, 'compositionstart', event => {
|
112
|
+
this.isComposing = true
|
113
|
+
})
|
114
|
+
|
115
|
+
this.addEvent(input, 'compositionend', event => {
|
116
|
+
this.isComposing = false
|
117
|
+
})
|
118
|
+
|
119
|
+
let lastValue = ''
|
120
|
+
|
121
|
+
this.addEvent(input, 'keydown', async event => {
|
122
|
+
const key = getKey(event)
|
123
|
+
if ((key === 'enter') && (! this.isComposing)) {
|
124
|
+
await this.addTagIfNeeded(input.value)
|
125
|
+
}
|
126
|
+
else if ((key === 'backspace') && (lastValue === '')) {
|
127
|
+
this.removeTagIfNeeded()
|
128
|
+
}
|
129
|
+
lastValue = input.value
|
130
|
+
})
|
131
|
+
|
132
|
+
this.addEvent(input, 'input', event => {
|
133
|
+
this.raf(() => {
|
134
|
+
const textWidth = this.getTextWidth(input.value, font)
|
135
|
+
const nextWidth = this.getNextInputWidth(textWidth)
|
136
|
+
input.style.width = nextWidth + 'px'
|
137
|
+
})
|
138
|
+
})
|
139
|
+
}
|
140
|
+
|
141
|
+
destroy() {
|
142
|
+
this.tags.forEach(tag => tag.remove())
|
143
|
+
this.input.remove()
|
144
|
+
}
|
145
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import raf from '../utils/raf'
|
2
2
|
import isUndef from '../utils/isUndef'
|
3
3
|
import { getDomPos, range, toPixel, isFunction } from '../utils'
|
4
4
|
|
@@ -6,6 +6,11 @@ export default function chartCommon(target) {
|
|
6
6
|
|
7
7
|
return class extends target {
|
8
8
|
|
9
|
+
constructor(...args) {
|
10
|
+
super(...args)
|
11
|
+
this.raf = raf
|
12
|
+
}
|
13
|
+
|
9
14
|
init() {
|
10
15
|
this.layers = []
|
11
16
|
if (isFunction(super.init)) {
|
@@ -159,13 +164,6 @@ export default function chartCommon(target) {
|
|
159
164
|
return this.ctx.measureText(value).width
|
160
165
|
}
|
161
166
|
|
162
|
-
raf(fn) {
|
163
|
-
if (isDef(window.requestAnimationFrame)) {
|
164
|
-
return window.requestAnimationFrame(fn)
|
165
|
-
}
|
166
|
-
return fn()
|
167
|
-
}
|
168
|
-
|
169
167
|
removeAllLayers() {
|
170
168
|
const { dom } = this
|
171
169
|
this.layers.forEach(layer => {
|
data/src/js/index.js
CHANGED
@@ -20,6 +20,7 @@ import Navbar from './components/Navbar'
|
|
20
20
|
import Radio from './components/Radio'
|
21
21
|
import SearchDropdown from './components/SearchDropdown'
|
22
22
|
import Sidebar from './components/Sidebar'
|
23
|
+
import TagInput from './components/TagInput'
|
23
24
|
import Tabbox from './components/Tabbox'
|
24
25
|
import Timepicker from './components/Timepicker'
|
25
26
|
import Toast from './components/Toast'
|
@@ -55,6 +56,7 @@ export {
|
|
55
56
|
Radio,
|
56
57
|
SearchDropdown,
|
57
58
|
Sidebar,
|
59
|
+
TagInput,
|
58
60
|
Tabbox,
|
59
61
|
Timepicker,
|
60
62
|
Toast,
|
data/src/js/utils/getKey.js
CHANGED
data/src/js/utils/raf.js
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
@keyframes shake {
|
2
|
+
0% { transform: translate(1px, 1px) rotate(0deg); }
|
3
|
+
10% { transform: translate(-1px, -2px) rotate(-1deg); }
|
4
|
+
20% { transform: translate(-3px, 0px) rotate(1deg); }
|
5
|
+
30% { transform: translate(3px, 2px) rotate(0deg); }
|
6
|
+
40% { transform: translate(1px, -1px) rotate(1deg); }
|
7
|
+
50% { transform: translate(-1px, 2px) rotate(-1deg); }
|
8
|
+
60% { transform: translate(-3px, 1px) rotate(0deg); }
|
9
|
+
70% { transform: translate(3px, 1px) rotate(-1deg); }
|
10
|
+
80% { transform: translate(-1px, -1px) rotate(1deg); }
|
11
|
+
90% { transform: translate(1px, 2px) rotate(0deg); }
|
12
|
+
100% { transform: translate(1px, -2px) rotate(-1deg); }
|
13
|
+
}
|
data/src/sass/_beyond.scss
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
@import './vendor/_turbolink';
|
6
6
|
@import './base/_background';
|
7
7
|
@import './base/_typography';
|
8
|
+
@import './_animations';
|
8
9
|
@import './_main';
|
9
10
|
@import './layout/_border-util';
|
10
11
|
@import './layout/_col';
|
@@ -44,6 +45,7 @@
|
|
44
45
|
@import './components/_tabbox';
|
45
46
|
@import './components/_table';
|
46
47
|
@import './components/_tag';
|
48
|
+
@import './components/_tag-input';
|
47
49
|
@import './components/_time-input';
|
48
50
|
@import './components/_time-menu';
|
49
51
|
@import './components/_toast';
|
@@ -0,0 +1,26 @@
|
|
1
|
+
.tag-input {
|
2
|
+
cursor: text;
|
3
|
+
background-color: #fff;
|
4
|
+
padding: .4em .4em 0 .4em;
|
5
|
+
min-height: 40px;
|
6
|
+
> input {
|
7
|
+
border: 0;
|
8
|
+
&:focus {
|
9
|
+
outline: none;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
.tag {
|
13
|
+
padding-right: 0;
|
14
|
+
display: inline-flex;
|
15
|
+
align-items: center;
|
16
|
+
margin-right: .7em;
|
17
|
+
margin-bottom: .7em;
|
18
|
+
> button {
|
19
|
+
border: 0;
|
20
|
+
background-color: transparent;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
&.shake {
|
24
|
+
animation: shake .5s;
|
25
|
+
}
|
26
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beyond-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.230
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kmsheng
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- src/js/components/SearchDropdown.js
|
145
145
|
- src/js/components/Sidebar.js
|
146
146
|
- src/js/components/Tabbox.js
|
147
|
+
- src/js/components/TagInput.js
|
147
148
|
- src/js/components/TimeInput.js
|
148
149
|
- src/js/components/TimeMenu.js
|
149
150
|
- src/js/components/Timepicker.js
|
@@ -194,11 +195,14 @@ files:
|
|
194
195
|
- src/js/utils/index.js
|
195
196
|
- src/js/utils/isDef.js
|
196
197
|
- src/js/utils/isInt.js
|
198
|
+
- src/js/utils/isStr.js
|
197
199
|
- src/js/utils/isTouchDevice.js
|
198
200
|
- src/js/utils/isUndef.js
|
199
201
|
- src/js/utils/msToS.js
|
200
202
|
- src/js/utils/promisify.js
|
203
|
+
- src/js/utils/raf.js
|
201
204
|
- src/js/utils/unbindAll.js
|
205
|
+
- src/sass/_animations.scss
|
202
206
|
- src/sass/_beyond-sprockets.scss
|
203
207
|
- src/sass/_beyond.scss
|
204
208
|
- src/sass/_main.scss
|
@@ -239,6 +243,7 @@ files:
|
|
239
243
|
- src/sass/components/_switch.scss
|
240
244
|
- src/sass/components/_tabbox.scss
|
241
245
|
- src/sass/components/_table.scss
|
246
|
+
- src/sass/components/_tag-input.scss
|
242
247
|
- src/sass/components/_tag.scss
|
243
248
|
- src/sass/components/_time-input.scss
|
244
249
|
- src/sass/components/_time-menu.scss
|