@operato/input 0.2.35 → 0.2.42
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.
- package/CHANGELOG.md +52 -0
- package/demo/index-3dish.html +15 -2
- package/demo/index-angle.html +9 -4
- package/demo/index-barcode.html +66 -0
- package/demo/index-button-radio.html +18 -6
- package/demo/index-checkbox.html +17 -9
- package/demo/index-select.html +118 -0
- package/demo/index-stack.html +15 -3
- package/demo/index.html +42 -86
- package/dist/src/ox-buttons-radio.d.ts +7 -5
- package/dist/src/ox-buttons-radio.js +18 -10
- package/dist/src/ox-buttons-radio.js.map +1 -1
- package/dist/src/ox-checkbox.d.ts +5 -6
- package/dist/src/ox-checkbox.js +33 -33
- package/dist/src/ox-checkbox.js.map +1 -1
- package/dist/src/ox-formfield.d.ts +10 -0
- package/dist/src/ox-formfield.js +38 -0
- package/dist/src/ox-formfield.js.map +1 -0
- package/dist/src/ox-input-3dish.d.ts +15 -14
- package/dist/src/ox-input-3dish.js +49 -23
- package/dist/src/ox-input-3dish.js.map +1 -1
- package/dist/src/ox-input-angle.d.ts +4 -5
- package/dist/src/ox-input-angle.js +15 -13
- package/dist/src/ox-input-angle.js.map +1 -1
- package/dist/src/ox-input-barcode.d.ts +22 -0
- package/dist/src/ox-input-barcode.js +205 -0
- package/dist/src/ox-input-barcode.js.map +1 -0
- package/dist/src/ox-input-stack.d.ts +5 -3
- package/dist/src/ox-input-stack.js +44 -35
- package/dist/src/ox-input-stack.js.map +1 -1
- package/dist/src/ox-select.d.ts +5 -4
- package/dist/src/ox-select.js +34 -12
- package/dist/src/ox-select.js.map +1 -1
- package/dist/test/property-angle.test.js +3 -3
- package/dist/test/property-angle.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/src/ox-buttons-radio.ts +22 -10
- package/src/ox-checkbox.ts +37 -33
- package/src/ox-formfield.ts +36 -0
- package/src/ox-input-3dish.ts +63 -29
- package/src/ox-input-angle.ts +19 -14
- package/src/ox-input-barcode.ts +203 -0
- package/src/ox-input-stack.ts +49 -24
- package/src/ox-select.ts +46 -16
- package/test/property-angle.test.ts +3 -4
@@ -0,0 +1,203 @@
|
|
1
|
+
import '@operato/popup'
|
2
|
+
|
3
|
+
import { css, html } from 'lit'
|
4
|
+
import { customElement, property, query, state } from 'lit/decorators.js'
|
5
|
+
|
6
|
+
import { OxPopup } from '@operato/popup'
|
7
|
+
import { BrowserMultiFormatReader } from '@zxing/library'
|
8
|
+
|
9
|
+
import { OxFormField } from './ox-formfield'
|
10
|
+
|
11
|
+
const barcodeIcon = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAYBAMAAAAfR1CMAAADKGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNjM4RURDQkQ1OUExMUU5QkExMkQ4NUY3NkMxNzBFOSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNjM4RURDQ0Q1OUExMUU5QkExMkQ4NUY3NkMxNzBFOSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2MzhFREM5RDU5QTExRTlCQTEyRDg1Rjc2QzE3MEU5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2MzhFRENBRDU5QTExRTlCQTEyRDg1Rjc2QzE3MEU5Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+55pr/QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkUExURQAAAEdwTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEus/7UCWQwAAAALdFJOU9YAg3wKBFBDSz9PnvQNDgAAAE9JREFUGNNjEEQFDKLJSnCOklkgg9QUJFn3RgZhRyS+iCGDEIp2RSBfQICRkRGIgTSQL4jCF6ScvxsZYOFT2T50/6D7Fz080MMLPTzRwhsAHVspfelur08AAAAASUVORK5CYII=`
|
12
|
+
|
13
|
+
@customElement('ox-input-barcode')
|
14
|
+
export class OxInputBarcode extends OxFormField {
|
15
|
+
static styles = [
|
16
|
+
css`
|
17
|
+
:host {
|
18
|
+
display: flex;
|
19
|
+
align-items: center;
|
20
|
+
border: none;
|
21
|
+
overflow: hidden;
|
22
|
+
background-color: #fff;
|
23
|
+
|
24
|
+
padding: var(--custom-input-barcode-field-padding) !important;
|
25
|
+
}
|
26
|
+
|
27
|
+
* {
|
28
|
+
align-self: stretch;
|
29
|
+
}
|
30
|
+
|
31
|
+
*:focus {
|
32
|
+
outline: none;
|
33
|
+
}
|
34
|
+
|
35
|
+
input {
|
36
|
+
flex: 1 !important;
|
37
|
+
border: none;
|
38
|
+
font: var(--custom-input-barcode-field-font);
|
39
|
+
width: 10px;
|
40
|
+
flex-grow: 1;
|
41
|
+
}
|
42
|
+
|
43
|
+
#scan-button {
|
44
|
+
display: block;
|
45
|
+
width: 30px;
|
46
|
+
height: 100%;
|
47
|
+
min-height: 24px;
|
48
|
+
border: none;
|
49
|
+
background-color: transparent;
|
50
|
+
background-repeat: no-repeat;
|
51
|
+
background-position: center;
|
52
|
+
background-image: var(--barcodescan-input-button-icon);
|
53
|
+
}
|
54
|
+
|
55
|
+
#scan-button[hidden] {
|
56
|
+
display: none;
|
57
|
+
}
|
58
|
+
|
59
|
+
ox-popup {
|
60
|
+
position: fixed;
|
61
|
+
|
62
|
+
width: 80vw;
|
63
|
+
height: 80vh;
|
64
|
+
transform: translate(10%, 10%);
|
65
|
+
}
|
66
|
+
|
67
|
+
video {
|
68
|
+
width: 100%;
|
69
|
+
height: 100%;
|
70
|
+
}
|
71
|
+
|
72
|
+
@media screen and (max-width: 460px) {
|
73
|
+
ox-popup {
|
74
|
+
position: fixed;
|
75
|
+
left: 0;
|
76
|
+
top: 0;
|
77
|
+
width: 100vw;
|
78
|
+
height: 100vh;
|
79
|
+
transform: translate(0%, 0%);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
`
|
83
|
+
]
|
84
|
+
|
85
|
+
@property({ type: String, attribute: true }) name?: string
|
86
|
+
@property({ type: Boolean }) scannable?: boolean
|
87
|
+
@property({ attribute: 'without-enter', type: Boolean }) withoutEnter?: boolean
|
88
|
+
@property({ type: String }) value?: string
|
89
|
+
|
90
|
+
@state() stream?: MediaStream
|
91
|
+
@state() reader?: BrowserMultiFormatReader
|
92
|
+
|
93
|
+
@query('input') input!: HTMLInputElement
|
94
|
+
@query('ox-popup') popup!: OxPopup
|
95
|
+
@query('video') video!: HTMLVideoElement
|
96
|
+
|
97
|
+
connectedCallback() {
|
98
|
+
super.connectedCallback()
|
99
|
+
|
100
|
+
this.scannable = false
|
101
|
+
|
102
|
+
if (navigator.mediaDevices) {
|
103
|
+
;(async () => {
|
104
|
+
try {
|
105
|
+
var stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } })
|
106
|
+
if (stream) {
|
107
|
+
stream.getTracks().forEach(track => track.stop())
|
108
|
+
this.scannable = true
|
109
|
+
}
|
110
|
+
} catch (e) {
|
111
|
+
console.warn('this device not support camera for barcode scan', e)
|
112
|
+
}
|
113
|
+
})()
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
disconnectedCallback() {
|
118
|
+
this.stopScan()
|
119
|
+
}
|
120
|
+
|
121
|
+
render() {
|
122
|
+
this.style.setProperty('--barcodescan-input-button-icon', `url(${barcodeIcon})`)
|
123
|
+
|
124
|
+
return html`
|
125
|
+
<input type="text" .value=${this.value || ''} maxlength="50" @change=${(e: Event) => this.onChange(e)} />
|
126
|
+
<button
|
127
|
+
?hidden=${!this.scannable}
|
128
|
+
id="scan-button"
|
129
|
+
@click=${(e: MouseEvent) => {
|
130
|
+
this.scan(e)
|
131
|
+
}}
|
132
|
+
></button>
|
133
|
+
|
134
|
+
<ox-popup
|
135
|
+
@focusout=${() => {
|
136
|
+
this.stopScan()
|
137
|
+
}}
|
138
|
+
>
|
139
|
+
<video></video>
|
140
|
+
</ox-popup>
|
141
|
+
`
|
142
|
+
}
|
143
|
+
|
144
|
+
onChange(e: Event) {
|
145
|
+
this.value = (e.target as HTMLInputElement)?.value
|
146
|
+
//@ts-ignore
|
147
|
+
this.dispatchEvent(new e.constructor(e.type, e))
|
148
|
+
}
|
149
|
+
|
150
|
+
async scan(e: MouseEvent) {
|
151
|
+
try {
|
152
|
+
this.popup.open({})
|
153
|
+
|
154
|
+
/* template.video가 생성된 후에 접근하기 위해서, 한 프레임을 강제로 건너뛴다. */
|
155
|
+
await this.updateComplete
|
156
|
+
|
157
|
+
var constraints = { video: { facingMode: 'environment' } } /* backside camera first */
|
158
|
+
this.stream = await navigator.mediaDevices.getUserMedia(constraints)
|
159
|
+
|
160
|
+
this.reader = new BrowserMultiFormatReader()
|
161
|
+
if (getComputedStyle(this.popup).display !== 'none' /* popup not hidden */ && this.stream) {
|
162
|
+
var result = await this.reader.decodeOnceFromStream(this.stream, this.video)
|
163
|
+
var input = this.input
|
164
|
+
input.focus()
|
165
|
+
input.value = String(result)
|
166
|
+
|
167
|
+
if (!this.withoutEnter) {
|
168
|
+
input.dispatchEvent(new KeyboardEvent('keypress', { keyCode: 0x0d }))
|
169
|
+
input.dispatchEvent(
|
170
|
+
new CustomEvent('change', {
|
171
|
+
bubbles: true,
|
172
|
+
composed: true,
|
173
|
+
detail: String(result)
|
174
|
+
})
|
175
|
+
)
|
176
|
+
}
|
177
|
+
} else {
|
178
|
+
/* popup이 비동기 진행 중에 close된 경우라면, stopScan()을 처리하지 못하게 되므로, 다시한번 clear해준다. */
|
179
|
+
this.stopScan()
|
180
|
+
}
|
181
|
+
} catch (err) {
|
182
|
+
/*
|
183
|
+
* 1. stream device 문제로 예외 발생한 경우.
|
184
|
+
* 2. 뒤로가기 등으로 popup이 종료된 경우에도 NotFoundException: Video stream has ended before any code could be detected. 이 발생한다.
|
185
|
+
*/
|
186
|
+
console.warn(err)
|
187
|
+
} finally {
|
188
|
+
this.popup.close()
|
189
|
+
|
190
|
+
this.stopScan()
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
stopScan() {
|
195
|
+
this.video.pause()
|
196
|
+
|
197
|
+
this.stream && this.stream.getTracks().forEach(track => track.stop())
|
198
|
+
this.reader && this.reader.reset()
|
199
|
+
|
200
|
+
delete this.stream
|
201
|
+
delete this.reader
|
202
|
+
}
|
203
|
+
}
|
package/src/ox-input-stack.ts
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
* @license Copyright © HatioLab Inc. All rights reserved.
|
3
3
|
*/
|
4
4
|
|
5
|
-
import { css, html
|
5
|
+
import { css, html } from 'lit'
|
6
6
|
import { customElement, property } from 'lit/decorators.js'
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
import { OxFormField } from './ox-formfield'
|
9
|
+
|
10
|
+
@customElement('ox-input-stack')
|
11
|
+
export default class OxInputStack extends OxFormField {
|
10
12
|
static styles = [
|
11
13
|
css`
|
12
14
|
:host {
|
@@ -43,12 +45,12 @@ export default class OxStack extends LitElement {
|
|
43
45
|
/**
|
44
46
|
* `stack`은 stack에 의해 만들어진 층의 배열을 유지한다.
|
45
47
|
*/
|
46
|
-
@property({ type: Array }) stack: { name: string }[] = []
|
48
|
+
@property({ type: Array }) stack: { name: string; active?: boolean }[] = []
|
47
49
|
|
48
50
|
/**
|
49
51
|
* `activeIndex`은 현재 active된 층의 인덱스를 유지한다.
|
50
52
|
*/
|
51
|
-
@property({ type: Number }) activeIndex: number = 0
|
53
|
+
// @property({ type: Number }) activeIndex: number = 0
|
52
54
|
|
53
55
|
render() {
|
54
56
|
const stack = [...this.stack].reverse()
|
@@ -59,11 +61,7 @@ export default class OxStack extends LitElement {
|
|
59
61
|
|
60
62
|
${stack.map(
|
61
63
|
(item, index) => html`
|
62
|
-
<div
|
63
|
-
?active=${length - index - 1 == this.activeIndex}
|
64
|
-
@click=${(e: Event) => this._onClickToActive(e)}
|
65
|
-
idx=${length - index - 1}
|
66
|
-
>
|
64
|
+
<div floor ?active=${item.active} @click=${(e: Event) => this._onClickToActive(e)} idx=${length - index - 1}>
|
67
65
|
${item.name} <button @click=${(e: Event) => this._onClickRemoveFloor(e)}>-</button>
|
68
66
|
</div>
|
69
67
|
`
|
@@ -71,39 +69,66 @@ export default class OxStack extends LitElement {
|
|
71
69
|
`
|
72
70
|
}
|
73
71
|
|
72
|
+
_notifyChange() {
|
73
|
+
this.value = this.stack
|
74
|
+
|
75
|
+
this.dispatchEvent(
|
76
|
+
new CustomEvent('change', {
|
77
|
+
detail: this.value,
|
78
|
+
bubbles: true,
|
79
|
+
composed: true
|
80
|
+
})
|
81
|
+
)
|
82
|
+
}
|
83
|
+
|
74
84
|
_onClickAddFloor(e: Event) {
|
75
85
|
this.stack.push({ name: String(this.stack.length + 1) })
|
76
86
|
this.requestUpdate()
|
87
|
+
|
88
|
+
this._notifyChange()
|
77
89
|
}
|
78
90
|
|
79
91
|
_onClickToActive(e: Event) {
|
80
|
-
const
|
81
|
-
|
92
|
+
const floor = (e.target as HTMLElement).closest('[floor]')
|
93
|
+
|
94
|
+
if (!floor) {
|
82
95
|
return
|
83
96
|
}
|
84
97
|
|
85
|
-
|
98
|
+
e.stopPropagation()
|
99
|
+
|
100
|
+
const activeIndex = Number(floor.getAttribute('idx'))
|
101
|
+
this.stack = this.stack.map((floor, index) => {
|
102
|
+
return activeIndex === index
|
103
|
+
? {
|
104
|
+
name: floor.name,
|
105
|
+
active: true
|
106
|
+
}
|
107
|
+
: { name: floor.name }
|
108
|
+
})
|
109
|
+
|
110
|
+
this._notifyChange()
|
86
111
|
}
|
87
112
|
|
88
113
|
_onClickRemoveFloor(e: Event) {
|
89
|
-
const
|
114
|
+
const floor = (e.target as HTMLElement).closest('[floor]')
|
90
115
|
|
91
|
-
if (
|
116
|
+
if (!floor) {
|
92
117
|
return
|
93
118
|
}
|
94
119
|
|
95
|
-
|
120
|
+
e.stopPropagation()
|
96
121
|
|
97
|
-
|
122
|
+
const idx = Number(floor.getAttribute('idx'))
|
98
123
|
|
99
|
-
|
100
|
-
this.activeIndex = 0
|
101
|
-
} else if (this.activeIndex >= idx) {
|
102
|
-
this.activeIndex--
|
103
|
-
} else if (this.activeIndex >= this.stack.length) {
|
104
|
-
this.activeIndex = 0
|
105
|
-
}
|
124
|
+
this.stack.splice(idx, 1)
|
106
125
|
|
107
126
|
this.requestUpdate()
|
127
|
+
|
128
|
+
this._notifyChange()
|
129
|
+
}
|
130
|
+
|
131
|
+
protected appendFormData({ formData }: FormDataEvent): void {
|
132
|
+
this.name && formData.append(this.name, JSON.stringify(this.value))
|
108
133
|
}
|
109
134
|
}
|
package/src/ox-select.ts
CHANGED
@@ -5,18 +5,20 @@
|
|
5
5
|
import '@material/mwc-icon'
|
6
6
|
import '@operato/popup'
|
7
7
|
|
8
|
-
import {
|
9
|
-
import { customElement, property
|
8
|
+
import { css, html } from 'lit'
|
9
|
+
import { customElement, property } from 'lit/decorators.js'
|
10
10
|
|
11
|
-
import {
|
12
|
-
|
11
|
+
import { OxPopupList } from '@operato/popup'
|
12
|
+
|
13
|
+
import { OxFormField } from './ox-formfield'
|
13
14
|
|
14
15
|
@customElement('ox-select')
|
15
|
-
export class Select extends
|
16
|
+
export class Select extends OxFormField {
|
16
17
|
static styles = [
|
17
18
|
css`
|
18
19
|
:host {
|
19
20
|
display: block;
|
21
|
+
position: relative;
|
20
22
|
}
|
21
23
|
|
22
24
|
div {
|
@@ -29,6 +31,9 @@ export class Select extends LitElement {
|
|
29
31
|
|
30
32
|
span {
|
31
33
|
flex: 1;
|
34
|
+
overflow: hidden;
|
35
|
+
text-overflow: ellipsis;
|
36
|
+
white-space: nowrap;
|
32
37
|
}
|
33
38
|
|
34
39
|
mwc-icon {
|
@@ -47,36 +52,61 @@ export class Select extends LitElement {
|
|
47
52
|
]
|
48
53
|
|
49
54
|
@property({ type: String }) name: string = ''
|
50
|
-
@property({ type: String })
|
55
|
+
@property({ type: String }) placeholder: string = ''
|
51
56
|
|
52
57
|
render() {
|
58
|
+
const label = (this.value instanceof Array ? this.value.join(', ') : this.value) || this.placeholder || ''
|
59
|
+
|
53
60
|
return html`
|
54
61
|
<div @click=${this.expand}>
|
55
|
-
<span>${
|
62
|
+
<span>${label}</span>
|
56
63
|
<mwc-icon>expand_more</mwc-icon>
|
57
64
|
</div>
|
65
|
+
|
58
66
|
<slot></slot>
|
59
67
|
`
|
60
68
|
}
|
61
69
|
|
70
|
+
connectedCallback() {
|
71
|
+
super.connectedCallback()
|
72
|
+
|
73
|
+
this.setAttribute('tabindex', '0')
|
74
|
+
|
75
|
+
this.addEventListener('select', (e: Event) => {
|
76
|
+
this.value = (e as CustomEvent).detail
|
77
|
+
|
78
|
+
this.dispatchEvent(
|
79
|
+
new CustomEvent('change', {
|
80
|
+
bubbles: true,
|
81
|
+
composed: true,
|
82
|
+
detail: this.value
|
83
|
+
})
|
84
|
+
)
|
85
|
+
})
|
86
|
+
|
87
|
+
this.addEventListener('keydown', (e: KeyboardEvent) => {
|
88
|
+
e.preventDefault()
|
89
|
+
|
90
|
+
if (e.key === ' ' || e.key == 'Spacebar' || e.key == 'ArrowDown') {
|
91
|
+
this.expand()
|
92
|
+
}
|
93
|
+
})
|
94
|
+
}
|
95
|
+
|
62
96
|
expand() {
|
63
|
-
const popupList = this.querySelector('ox-popup-list') as
|
97
|
+
const popupList = this.querySelector('ox-popup-list') as OxPopupList
|
64
98
|
|
65
99
|
if (popupList) {
|
66
100
|
popupList.style.width = `${this.offsetWidth}px`
|
67
101
|
|
68
102
|
popupList.open({
|
69
|
-
top: this.
|
70
|
-
left:
|
103
|
+
top: this.offsetHeight,
|
104
|
+
left: 0
|
71
105
|
})
|
72
106
|
}
|
73
107
|
}
|
74
108
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if (e.keyCode == 32 || e.code == 'Space') {
|
79
|
-
this.expand()
|
80
|
-
}
|
109
|
+
protected appendFormData({ formData }: FormDataEvent): void {
|
110
|
+
this.name && formData.append(this.name, JSON.stringify(this.value))
|
81
111
|
}
|
82
112
|
}
|
@@ -1,22 +1,21 @@
|
|
1
|
-
import { html } from 'lit'
|
2
|
-
|
3
1
|
import { expect, fixture } from '@open-wc/testing'
|
4
2
|
|
5
3
|
import { OxInputAngle } from '../src/ox-input-angle'
|
4
|
+
import { html } from 'lit'
|
6
5
|
|
7
6
|
describe('OxInputAngle', () => {
|
8
7
|
it('has a default title "Hey there" and angle 5', async () => {
|
9
8
|
const el = await fixture<OxInputAngle>(html`<ox-input-angle></ox-input-angle>`)
|
10
9
|
|
11
10
|
expect(el.title).to.equal('Hey there')
|
12
|
-
expect(el.
|
11
|
+
expect(el.value).to.equal(5)
|
13
12
|
})
|
14
13
|
|
15
14
|
it('increases the angle on button click', async () => {
|
16
15
|
const el = await fixture<OxInputAngle>(html`<ox-input-angle></ox-input-angle>`)
|
17
16
|
el.shadowRoot!.querySelector('button')!.click()
|
18
17
|
|
19
|
-
expect(el.
|
18
|
+
expect(el.value).to.equal(6)
|
20
19
|
})
|
21
20
|
|
22
21
|
it('can override the title via attribute', async () => {
|