@operato/input 8.0.0-alpha.51 → 8.0.0-beta.1

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 (99) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/tsconfig.tsbuildinfo +1 -1
  3. package/package.json +7 -7
  4. package/.editorconfig +0 -29
  5. package/.storybook/main.js +0 -3
  6. package/.storybook/preview.js +0 -52
  7. package/.storybook/server.mjs +0 -8
  8. package/src/index.ts +0 -35
  9. package/src/locale/locale-codes.ts +0 -18
  10. package/src/locale/locale-picker.ts +0 -43
  11. package/src/locale/localization.ts +0 -15
  12. package/src/locales/en.ts +0 -30
  13. package/src/locales/ko.ts +0 -30
  14. package/src/locales/ms.ts +0 -30
  15. package/src/locales/zh.ts +0 -30
  16. package/src/ox-buttons-radio.ts +0 -140
  17. package/src/ox-checkbox.ts +0 -181
  18. package/src/ox-form-field.ts +0 -53
  19. package/src/ox-input-3axis.ts +0 -77
  20. package/src/ox-input-3dish.ts +0 -211
  21. package/src/ox-input-angle.ts +0 -73
  22. package/src/ox-input-barcode.ts +0 -318
  23. package/src/ox-input-code.ts +0 -139
  24. package/src/ox-input-color-gradient.ts +0 -349
  25. package/src/ox-input-color-stops.ts +0 -525
  26. package/src/ox-input-color.ts +0 -338
  27. package/src/ox-input-container.ts +0 -32
  28. package/src/ox-input-crontab.ts +0 -595
  29. package/src/ox-input-data.ts +0 -219
  30. package/src/ox-input-direction.ts +0 -92
  31. package/src/ox-input-duration.ts +0 -175
  32. package/src/ox-input-file.ts +0 -209
  33. package/src/ox-input-hashtags.ts +0 -185
  34. package/src/ox-input-i18n-label.ts +0 -140
  35. package/src/ox-input-image.ts +0 -168
  36. package/src/ox-input-key-values.ts +0 -301
  37. package/src/ox-input-layout/ox-input-card-layout.ts +0 -58
  38. package/src/ox-input-layout/ox-input-grid-layout.ts +0 -64
  39. package/src/ox-input-layout/ox-input-layout.ts +0 -77
  40. package/src/ox-input-mass-fraction.ts +0 -437
  41. package/src/ox-input-multiple-colors.ts +0 -135
  42. package/src/ox-input-options.ts +0 -216
  43. package/src/ox-input-partition-keys.ts +0 -303
  44. package/src/ox-input-privilege.ts +0 -163
  45. package/src/ox-input-quantifier.ts +0 -62
  46. package/src/ox-input-range.ts +0 -146
  47. package/src/ox-input-scene-component-id.ts +0 -73
  48. package/src/ox-input-search.ts +0 -126
  49. package/src/ox-input-select-buttons.ts +0 -75
  50. package/src/ox-input-signature.ts +0 -208
  51. package/src/ox-input-stack.ts +0 -136
  52. package/src/ox-input-switch.ts +0 -117
  53. package/src/ox-input-table-column-config.ts +0 -211
  54. package/src/ox-input-table.ts +0 -404
  55. package/src/ox-input-textarea.ts +0 -86
  56. package/src/ox-input-unit-number.ts +0 -354
  57. package/src/ox-input-value-map.ts +0 -342
  58. package/src/ox-input-value-ranges.ts +0 -363
  59. package/src/ox-input-work-shift.ts +0 -290
  60. package/src/ox-select-floor.ts +0 -246
  61. package/src/ox-select.ts +0 -219
  62. package/stories/image-for-select-floor.ts +0 -2
  63. package/stories/ox-buttons-radio.stories.ts +0 -89
  64. package/stories/ox-checkbox.stories.ts +0 -111
  65. package/stories/ox-input-3axis.stories.ts +0 -77
  66. package/stories/ox-input-3dish.stories.ts +0 -106
  67. package/stories/ox-input-angle.stories.ts +0 -84
  68. package/stories/ox-input-barcode.stories.ts +0 -117
  69. package/stories/ox-input-code.stories.ts +0 -99
  70. package/stories/ox-input-crontab.stories.ts +0 -82
  71. package/stories/ox-input-data.stories.ts +0 -82
  72. package/stories/ox-input-direction.stories.ts +0 -91
  73. package/stories/ox-input-duration.stories.ts +0 -84
  74. package/stories/ox-input-file.stories.ts +0 -111
  75. package/stories/ox-input-hashtags.stories.ts +0 -82
  76. package/stories/ox-input-i18n-label.stories.ts +0 -103
  77. package/stories/ox-input-key-values.stories.ts +0 -97
  78. package/stories/ox-input-mass-fraction.stories.ts +0 -102
  79. package/stories/ox-input-multiple-colors.stories.ts +0 -72
  80. package/stories/ox-input-options.stories.ts +0 -80
  81. package/stories/ox-input-partition-keys.stories.ts +0 -84
  82. package/stories/ox-input-privilege.stories.ts +0 -108
  83. package/stories/ox-input-quantifier.stories.ts +0 -80
  84. package/stories/ox-input-range.stories.ts +0 -89
  85. package/stories/ox-input-search.stories.ts +0 -91
  86. package/stories/ox-input-select-buttons.stories.ts +0 -118
  87. package/stories/ox-input-signature.stories.ts +0 -75
  88. package/stories/ox-input-switch.stories.ts +0 -91
  89. package/stories/ox-input-table-column-config.stories.ts +0 -109
  90. package/stories/ox-input-unit.stories.ts +0 -151
  91. package/stories/ox-input-value-map.stories.ts +0 -92
  92. package/stories/ox-input-value-ranges.stories.ts +0 -92
  93. package/stories/ox-input-work-shift.stories.ts +0 -106
  94. package/stories/ox-select-floor.stories.ts +0 -197
  95. package/stories/ox-select-set-options.stories.ts +0 -208
  96. package/stories/ox-select.stories.ts +0 -181
  97. package/tsconfig.json +0 -25
  98. package/web-dev-server.config.mjs +0 -27
  99. package/web-test-runner.config.mjs +0 -41
@@ -1,318 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import '@operato/popup/ox-popup.js'
6
-
7
- import { css, html } from 'lit'
8
- import { customElement, property, query, state } from 'lit/decorators.js'
9
- import { scanImageData } from '@undecaf/zbar-wasm'
10
-
11
- import { OxPopup } from '@operato/popup'
12
-
13
- import { OxFormField } from './ox-form-field.js'
14
-
15
- const barcodeIcon = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAYBAMAAAAfR1CMAAADKGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNjM4RURDQkQ1OUExMUU5QkExMkQ4NUY3NkMxNzBFOSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNjM4RURDQ0Q1OUExMUU5QkExMkQ4NUY3NkMxNzBFOSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2MzhFREM5RDU5QTExRTlCQTEyRDg1Rjc2QzE3MEU5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2MzhFRENBRDU5QTExRTlCQTEyRDg1Rjc2QzE3MEU5Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+55pr/QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkUExURQAAAEdwTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEus/7UCWQwAAAALdFJOU9YAg3wKBFBDSz9PnvQNDgAAAE9JREFUGNNjEEQFDKLJSnCOklkgg9QUJFn3RgZhRyS+iCGDEIp2RSBfQICRkRGIgTSQL4jCF6ScvxsZYOFT2T50/6D7Fz080MMLPTzRwhsAHVspfelur08AAAAASUVORK5CYII=`
16
-
17
- /**
18
- * Custom input component for barcode scanning.
19
- *
20
- * This component provides a text input field and a barcode scanning button. Users can input text
21
- * manually or scan barcodes using the device camera. Supported barcode formats include:
22
- *
23
- * - Code-39
24
- * - Code-93
25
- * - Code-128
26
- * - Codabar
27
- * - Databar/Expanded
28
- * - EAN/GTIN-5/8/13
29
- * - ISBN-10/13
30
- * - ISBN-13+2
31
- * - ISBN-13+5
32
- * - ITF (Interleaved 2 of 5)
33
- * - QR Code
34
- * - UPC-A/E
35
- *
36
- * @fires CustomEvent#change - Dispatched when the input value changes.
37
- * @fires KeyboardEvent#keydown - Dispatched when the Enter key is pressed (if not withoutEnter).
38
- *
39
- * @cssprop {String} --barcodescan-input-button-icon - Icon for the barcode scanning button.
40
- *
41
- * @customElement
42
- */
43
- @customElement('ox-input-barcode')
44
- export class OxInputBarcode extends OxFormField {
45
- static styles = [
46
- css`
47
- :host {
48
- display: flex;
49
- align-items: center;
50
- border: none;
51
- background-color: transparent;
52
- height: var(--ox-input-height, var(--form-element-height-medium));
53
- }
54
-
55
- * {
56
- align-self: stretch;
57
- }
58
-
59
- *:focus {
60
- outline: none;
61
- }
62
-
63
- input {
64
- flex: 1;
65
- width: 10px; /* intentionally width set */
66
- border: var(--ox-input-border, 1px solid var(--md-sys-color-outline));
67
- border-radius: var(--ox-input-radius, var(--md-sys-shape-corner-small));
68
- background-color: var(--ox-input-background-color, var(--md-sys-color-on-primary));
69
- color: var(--ox-input-color, var(--md-sys-color-on-primary-container));
70
- font-size: var(--md-sys-typescale-label-large-size, 0.875rem);
71
-
72
- box-sizing: border-box;
73
- padding-right: 35px;
74
- }
75
-
76
- input:focus {
77
- outline: none;
78
- border-color: var(--md-sys-color-secondary-fixed-dim);
79
- }
80
-
81
- #scan-button {
82
- display: block;
83
- position: relative;
84
- margin-left: -35px;
85
- width: 35px;
86
- border: none;
87
- background: var(--barcodescan-input-button-icon) no-repeat center center;
88
- }
89
-
90
- #scan-button[hidden] {
91
- display: none;
92
- }
93
- `
94
- ]
95
-
96
- /**
97
- * Indicates whether barcode scanning is enabled.
98
- * @property {Boolean} scannable
99
- */
100
- @property({ type: Boolean, attribute: true }) scannable?: boolean
101
-
102
- /**
103
- * If true, the "Enter" key press event is not fired after scanning a barcode.
104
- * @property {Boolean} withoutEnter
105
- */
106
- @property({ attribute: 'without-enter', type: Boolean }) withoutEnter?: boolean
107
-
108
- /**
109
- * The value of the input field.
110
- * @property {String} declare value
111
- */
112
- @property({ type: String }) declare value?: string
113
-
114
- /**
115
- * If true, only English characters are allowed in the input field.
116
- * @property {Boolean} englishOnly
117
- */
118
- @property({ attribute: 'english-only', type: Boolean }) englishOnly?: boolean
119
-
120
- /**
121
- * If true, the input field is automatically selected after a change event.
122
- * @property {Boolean} selectAfterChange
123
- */
124
- @property({ attribute: 'select-after-change', type: Boolean }) selectAfterChange?: boolean
125
-
126
- @state() stream?: MediaStream
127
-
128
- @query('input') input!: HTMLInputElement
129
-
130
- private popup: OxPopup | null = null
131
- private video: HTMLVideoElement | null = null
132
-
133
- connectedCallback() {
134
- super.connectedCallback()
135
-
136
- if (navigator.mediaDevices) {
137
- ;(async () => {
138
- try {
139
- var stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: 'environment' } })
140
- if (stream) {
141
- stream.getTracks().forEach(track => track.stop())
142
- this.scannable = true
143
- }
144
- } catch (e) {
145
- this.scannable = false
146
- console.warn('this device not support camera for barcode scan', e)
147
- }
148
- })()
149
- } else {
150
- this.scannable = false
151
- }
152
- }
153
-
154
- disconnectedCallback() {
155
- this.stopScan()
156
- }
157
-
158
- render() {
159
- this.style.setProperty('--barcodescan-input-button-icon', `url(${barcodeIcon})`)
160
-
161
- return html`
162
- <input
163
- type="text"
164
- .value=${this.value || ''}
165
- @change=${(e: Event) => this.onInputChange(e)}
166
- @keydown=${(e: KeyboardEvent) => this.onInputKeyDown(e)}
167
- ?disabled=${this.disabled}
168
- />
169
- <button
170
- ?hidden=${!this.scannable}
171
- id="scan-button"
172
- @click=${(e: MouseEvent) => {
173
- this.scan(e)
174
- }}
175
- ?disabled=${this.disabled}
176
- ></button>
177
- `
178
- }
179
-
180
- onInputChange(e: Event) {
181
- e.stopPropagation()
182
-
183
- if (this.englishOnly) {
184
- /* englishOnly 인 경우에는 멀티바이트 문자들을 모두 제거한다. */
185
- this.value = this.input.value = this.input.value?.replace(/[^\x00-\x7F]/g, '')
186
- } else {
187
- this.value = this.input.value
188
- }
189
-
190
- if (this.selectAfterChange) {
191
- requestAnimationFrame(() => {
192
- this.input.select()
193
- })
194
- }
195
-
196
- this.dispatchEvent(
197
- new CustomEvent('change', {
198
- detail: this.value
199
- })
200
- )
201
- }
202
-
203
- onInputKeyDown(e: KeyboardEvent) {
204
- if (e.key === 'Enter' && !e.isComposing) {
205
- /* Even if the value has not changed, the enter key triggers a change event. */
206
- e.preventDefault() /* Prevent change event from occurring twice. */
207
-
208
- this.input.dispatchEvent(new CustomEvent('change'))
209
- } else if (this.englishOnly && !e.metaKey && !e.ctrlKey && !e.altKey && /^Key/.test(e.code)) {
210
- e.stopPropagation()
211
- e.preventDefault()
212
-
213
- /* englishOnly 인 경우에 문자들은 여기에서 처리한다. 멀티바이트 문자들이 대부분 알파벳의 자모음을 조합하므로, ... */
214
- const key = e.shiftKey ? e.code.charAt(3) : e.code.charAt(3).toLowerCase()
215
- const value = this.input.value
216
-
217
- const start = this.input.selectionStart || 0
218
- const end = this.input.selectionEnd || start
219
-
220
- this.input.value = [value.substring(0, start), key, value.substring(end)].join('')
221
- this.input.setSelectionRange(start + 1, start + 1)
222
- }
223
- }
224
-
225
- async scan(e: MouseEvent) {
226
- try {
227
- if (this.popup) {
228
- this.stopScan()
229
- }
230
-
231
- this.popup = OxPopup.open({
232
- template: html`
233
- <video></video>
234
- <md-icon
235
- style="position: fixed; right: 0; top: 0; color: red; tabindex: 0"
236
- @click=${() => {
237
- this.stopScan()
238
- }}
239
- >close</md-icon
240
- >
241
- `,
242
- width: '100vw',
243
- height: '100dvh'
244
- })
245
-
246
- this.video! = this.popup.querySelector('video') as HTMLVideoElement
247
-
248
- var constraints = { audio: false, video: { facingMode: 'environment' } } /* backside camera first */
249
- this.stream = await navigator.mediaDevices.getUserMedia(constraints)
250
-
251
- this.video.srcObject = this.stream
252
- this.video.play()
253
-
254
- this.video.onloadedmetadata = async e => {
255
- var canvas = new OffscreenCanvas(
256
- this.video!.videoWidth || this.video!.width,
257
- this.video!.videoHeight || this.video!.height
258
- )
259
-
260
- var context = canvas.getContext('2d', {
261
- willReadFrequently: true
262
- })
263
-
264
- const detect = async () => {
265
- try {
266
- if (!this.stream?.active) {
267
- return
268
- }
269
-
270
- context!.drawImage(this.video!, 0, 0, canvas.width, canvas.height)
271
- const imageData = context!.getImageData(0, 0, canvas.width, canvas.height)
272
- const symbols = await scanImageData(imageData)
273
- const result = symbols[0]?.decode()
274
-
275
- if (result) {
276
- this.stopScan()
277
-
278
- var input = this.input
279
- input.focus()
280
- this.value = input.value = String(result)
281
-
282
- if (!this.withoutEnter) {
283
- input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
284
- }
285
- } else {
286
- requestAnimationFrame(async () => await detect())
287
- }
288
- } catch (e) {
289
- console.warn(e)
290
- this.stopScan()
291
- }
292
- }
293
-
294
- await detect()
295
- }
296
- } catch (err) {
297
- /*
298
- * 1. stream device 문제로 예외 발생한 경우.
299
- * 2. 뒤로가기 등으로 popup이 종료된 경우에도 NotFoundException: Video stream has ended before any code could be detected. 이 발생한다.
300
- */
301
- console.warn(err)
302
- }
303
- }
304
-
305
- stopScan() {
306
- if (this.video) {
307
- this.video.pause()
308
- this.video.srcObject = null
309
- }
310
-
311
- if (this.popup) {
312
- this.popup.close()
313
- this.popup = null
314
- }
315
-
316
- this.stream?.getTracks().forEach(track => track.stop())
317
- }
318
- }
@@ -1,139 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import { css, PropertyValues } from 'lit'
6
- import { customElement, property } from 'lit/decorators.js'
7
-
8
- import { minimalSetup } from 'codemirror'
9
- import { history, historyKeymap, indentWithTab } from '@codemirror/commands'
10
- import { EditorView, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view'
11
- import { autocompletion, closeBrackets } from '@codemirror/autocomplete'
12
- import { bracketMatching, LanguageSupport, syntaxHighlighting } from '@codemirror/language'
13
- import { oneDarkHighlightStyle, oneDark } from '@codemirror/theme-one-dark'
14
-
15
- import { javascript } from '@codemirror/lang-javascript'
16
- import { sql } from '@codemirror/lang-sql'
17
- import { json } from '@codemirror/lang-json'
18
-
19
- import { ScrollbarStyles } from '@operato/styles'
20
- import { togglefullscreen } from '@operato/utils'
21
-
22
- import { OxFormField } from './ox-form-field'
23
-
24
- /**
25
- WEB Component for code-mirror code editor.
26
-
27
- Example:
28
-
29
- <ox-input-code .value=${text} language="javascript" show-line-numbers>
30
- </ox-input-code>
31
- */
32
- @customElement('ox-input-code')
33
- export class OxInputCode extends OxFormField {
34
- static styles = [
35
- ScrollbarStyles,
36
- css`
37
- :host {
38
- display: flex;
39
- flex-direction: column;
40
- position: relative;
41
- background: white;
42
- overflow: auto;
43
- border:1px solid var(--md-sys-color-outline);
44
- border-radius:var(--md-sys-shape-corner-small);
45
- }
46
-
47
- .cm-editor {
48
- flex: 1;
49
-
50
- }
51
- `
52
- ]
53
-
54
- /**
55
- * `value`는 에디터에서 작성중인 contents이다.
56
- */
57
- @property({ type: String }) value: string = ''
58
- @property({ type: Boolean, attribute: 'show-line-numbers' }) showLineNumbers: boolean = false
59
- @property({ type: String }) language?: string = 'javascript'
60
-
61
- private _self_changing: boolean = false
62
- private _editor?: EditorView
63
- private _changed: boolean = false
64
-
65
- updated(changes: PropertyValues<this>) {
66
- if (changes.has('value') && this.editor && !this._self_changing) {
67
- const to = this.editor.state.doc.toString().length
68
- this.editor.dispatch({
69
- changes: { from: 0, to, insert: this.value === undefined ? '' : String(this.value) }
70
- })
71
- }
72
- }
73
-
74
- get editor() {
75
- if (!this._editor) {
76
- let language: LanguageSupport[] = []
77
- switch (this.language) {
78
- case 'sql':
79
- language = [sql()]
80
- break
81
- case 'json':
82
- language = [json()]
83
- break
84
- case 'javascript':
85
- language = [javascript()]
86
- break
87
- default:
88
- break
89
- }
90
-
91
- this._editor = new EditorView({
92
- doc: this.value,
93
- extensions: [
94
- minimalSetup,
95
- ...language,
96
- ...(this.showLineNumbers ? [lineNumbers()] : []),
97
- bracketMatching(),
98
- closeBrackets(),
99
- history(),
100
- autocompletion(),
101
- oneDark,
102
- syntaxHighlighting(oneDarkHighlightStyle),
103
- highlightActiveLine(),
104
- keymap.of([...historyKeymap, indentWithTab]),
105
- EditorView.updateListener.of(async v => {
106
- if (v.docChanged) {
107
- this._self_changing = true
108
- this._changed = true
109
-
110
- await this.updateComplete
111
-
112
- this._self_changing = false
113
- }
114
- })
115
- ],
116
- parent: this.renderRoot
117
- })
118
- }
119
-
120
- this._editor.contentDOM.addEventListener('keydown', event => {
121
- event.stopPropagation()
122
-
123
- if (event.key === 'Escape') {
124
- togglefullscreen(this._editor!.contentDOM)
125
- }
126
- })
127
-
128
- this._editor.contentDOM.addEventListener('blur', e => {
129
- if (!this._changed) {
130
- return
131
- }
132
-
133
- this.value = this._editor!.state.doc.toString()
134
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
135
- })
136
-
137
- return this._editor
138
- }
139
- }