beyond-rails 0.0.229 → 0.0.230

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6eb3a6d0140c228f4cf167707a98fcc338f005de8f44fdfc160f8f0b31cc95fe
4
- data.tar.gz: 7bf45b85d53d4bfbb6856687d31e68fd23f53addaceb8e8c7783bc0847c60f93
3
+ metadata.gz: cf80575d0a2ac63e76f75b053115cd6c5518382878d406745c4f959d602d2767
4
+ data.tar.gz: b4c4372056bc1e9d5deddafbf62cadb8ab5ac8f53e3761a36f876b8b4db3897d
5
5
  SHA512:
6
- metadata.gz: 67f40335950e4e6874d3bd6e7869610d67f9fffffe7708647703036522403f754c733f74bb6e20824255ee408bc40224a1784d56916bcfcea1b9213faaec5e02
7
- data.tar.gz: dbd66629f50809e95d2cb86308ce40601bdccfb0681eb5167982c94a76e10a3bb217b12caa4f5484784a973ccb5dc844f25edb9f3e11042ca7c53f1d2a61884e
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 isDef from '../utils/isDef'
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 => {
@@ -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,
@@ -1,4 +1,5 @@
1
1
  const keyMap = {
2
+ 8: 'backspace',
2
3
  13: 'enter',
3
4
  17: 'ctrl',
4
5
  27: 'esc',
@@ -0,0 +1,3 @@
1
+ export default function isStr(value) {
2
+ return (typeof value === 'string')
3
+ }
@@ -0,0 +1,8 @@
1
+ import isDef from './isDef'
2
+
3
+ export default function raf(fn) {
4
+ if (isDef(window.requestAnimationFrame)) {
5
+ return window.requestAnimationFrame(fn)
6
+ }
7
+ return fn()
8
+ }
@@ -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
+ }
@@ -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.229
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