@operato/input 1.0.0-alpha.4 → 1.0.0-alpha.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +327 -0
  2. package/README.md +9 -6
  3. package/assets/images/icon-editor-gradient-direction.png +0 -0
  4. package/assets/images/icon-properties-label.png +0 -0
  5. package/assets/images/icon-properties-line-type.png +0 -0
  6. package/assets/images/icon-properties-table.png +0 -0
  7. package/demo/index-color-gradient.html +35 -0
  8. package/demo/index-color-stops.html +62 -0
  9. package/demo/index-color.html +35 -0
  10. package/demo/index-crontab.html +36 -0
  11. package/demo/index-file.html +41 -0
  12. package/demo/index-image.html +1 -1
  13. package/demo/index-multiple-colors.html +37 -0
  14. package/demo/index-options.html +43 -0
  15. package/demo/index-partition-keys.html +71 -0
  16. package/demo/index-range.html +40 -0
  17. package/demo/index-select.html +21 -14
  18. package/demo/index-table.html +39 -0
  19. package/demo/index-value-map.html +80 -0
  20. package/demo/index-value-ranges.html +80 -0
  21. package/demo/index.html +23 -54
  22. package/dist/src/index.d.ts +21 -11
  23. package/dist/src/index.js +21 -11
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/ox-checkbox.d.ts +1 -1
  26. package/dist/src/ox-checkbox.js +2 -2
  27. package/dist/src/ox-checkbox.js.map +1 -1
  28. package/dist/src/ox-input-code.d.ts +4 -4
  29. package/dist/src/ox-input-code.js +8 -8
  30. package/dist/src/ox-input-code.js.map +1 -1
  31. package/dist/src/ox-input-color-gradient.d.ts +26 -0
  32. package/dist/src/ox-input-color-gradient.js +318 -0
  33. package/dist/src/ox-input-color-gradient.js.map +1 -0
  34. package/dist/src/ox-input-color-stops.d.ts +71 -0
  35. package/dist/src/ox-input-color-stops.js +445 -0
  36. package/dist/src/ox-input-color-stops.js.map +1 -0
  37. package/dist/src/ox-input-color.d.ts +176 -0
  38. package/dist/src/ox-input-color.js +298 -0
  39. package/dist/src/ox-input-color.js.map +1 -0
  40. package/dist/src/ox-input-crontab.d.ts +23 -0
  41. package/dist/src/ox-input-crontab.js +560 -0
  42. package/dist/src/ox-input-crontab.js.map +1 -0
  43. package/dist/src/ox-input-data.d.ts +2 -2
  44. package/dist/src/ox-input-data.js +2 -2
  45. package/dist/src/ox-input-data.js.map +1 -1
  46. package/dist/src/ox-input-file.d.ts +2 -0
  47. package/dist/src/ox-input-file.js +6 -1
  48. package/dist/src/ox-input-file.js.map +1 -1
  49. package/dist/src/ox-input-layout/ox-input-card-layout.d.ts +4 -0
  50. package/dist/src/ox-input-layout/ox-input-card-layout.js +57 -0
  51. package/dist/src/ox-input-layout/ox-input-card-layout.js.map +1 -0
  52. package/dist/src/ox-input-layout/ox-input-grid-layout.d.ts +4 -0
  53. package/dist/src/ox-input-layout/ox-input-grid-layout.js +63 -0
  54. package/dist/src/ox-input-layout/ox-input-grid-layout.js.map +1 -0
  55. package/dist/src/ox-input-layout/ox-input-layout.d.ts +5 -0
  56. package/dist/src/ox-input-layout/ox-input-layout.js +73 -0
  57. package/dist/src/ox-input-layout/ox-input-layout.js.map +1 -0
  58. package/dist/src/ox-input-multiple-colors.d.ts +28 -0
  59. package/dist/src/ox-input-multiple-colors.js +113 -0
  60. package/dist/src/ox-input-multiple-colors.js.map +1 -0
  61. package/dist/src/ox-input-options.d.ts +22 -0
  62. package/dist/src/ox-input-options.js +137 -0
  63. package/dist/src/ox-input-options.js.map +1 -0
  64. package/dist/src/ox-input-partition-keys.d.ts +36 -0
  65. package/dist/src/ox-input-partition-keys.js +204 -0
  66. package/dist/src/ox-input-partition-keys.js.map +1 -0
  67. package/dist/src/ox-input-range.d.ts +4 -0
  68. package/dist/src/ox-input-range.js +161 -0
  69. package/dist/src/ox-input-range.js.map +1 -0
  70. package/dist/src/ox-input-scene-component-id.d.ts +11 -0
  71. package/dist/src/ox-input-scene-component-id.js +68 -0
  72. package/dist/src/ox-input-scene-component-id.js.map +1 -0
  73. package/dist/src/ox-input-stack.d.ts +1 -1
  74. package/dist/src/ox-input-stack.js +1 -1
  75. package/dist/src/ox-input-stack.js.map +1 -1
  76. package/dist/src/ox-input-table.d.ts +8 -0
  77. package/dist/src/ox-input-table.js +379 -0
  78. package/dist/src/ox-input-table.js.map +1 -0
  79. package/dist/src/ox-input-value-map.d.ts +41 -0
  80. package/dist/src/ox-input-value-map.js +279 -0
  81. package/dist/src/ox-input-value-map.js.map +1 -0
  82. package/dist/src/ox-input-value-ranges.d.ts +41 -0
  83. package/dist/src/ox-input-value-ranges.js +298 -0
  84. package/dist/src/ox-input-value-ranges.js.map +1 -0
  85. package/dist/src/ox-select.d.ts +3 -0
  86. package/dist/src/ox-select.js +28 -3
  87. package/dist/src/ox-select.js.map +1 -1
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +25 -7
  90. package/src/index.ts +21 -11
  91. package/src/ox-checkbox.ts +3 -3
  92. package/src/ox-input-code.ts +9 -10
  93. package/src/ox-input-color-gradient.ts +343 -0
  94. package/src/ox-input-color-stops.ts +499 -0
  95. package/src/ox-input-color.ts +323 -0
  96. package/src/ox-input-crontab.ts +560 -0
  97. package/src/ox-input-data.ts +5 -5
  98. package/src/ox-input-file.ts +8 -3
  99. package/src/ox-input-layout/ox-input-card-layout.ts +58 -0
  100. package/src/ox-input-layout/ox-input-grid-layout.ts +64 -0
  101. package/src/ox-input-layout/ox-input-layout.ts +77 -0
  102. package/src/ox-input-multiple-colors.ts +113 -0
  103. package/src/ox-input-options.ts +165 -0
  104. package/src/ox-input-partition-keys.ts +243 -0
  105. package/src/ox-input-range.ts +147 -0
  106. package/src/{ox-input-id.ts → ox-input-scene-component-id.ts} +1 -1
  107. package/src/ox-input-stack.ts +1 -1
  108. package/src/ox-input-table.ts +404 -0
  109. package/src/{ox-input-keyvalues.ts.ing → ox-input-value-map.ts} +125 -94
  110. package/src/ox-input-value-ranges.ts +325 -0
  111. package/src/ox-select.ts +31 -5
  112. package/translations/en.json +1 -0
  113. package/translations/ko.json +1 -0
  114. package/translations/ms.json +1 -0
  115. package/translations/zh.json +1 -0
  116. package/src/ox-input-ranges.ts.ing +0 -292
@@ -0,0 +1,499 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import './ox-input-color'
6
+
7
+ import { PropertyValues, css, html } from 'lit'
8
+ import { customElement, property, query } from 'lit/decorators.js'
9
+
10
+ import { OxFormField } from './ox-form-field'
11
+ import { OxInputColor } from './ox-input-color'
12
+ import deepEquals from 'lodash-es/isEqual'
13
+
14
+ export type ColorStop = {
15
+ color: string
16
+ position: number
17
+ }
18
+
19
+ /**
20
+ 범위내에서 여러 컬러셋(포지션과 색깔) 배열을 편집하는 컴포넌트이다.
21
+
22
+ 미리보기 Bar에서는 gradient나, solid 형태의 컬러셋을 보여준다.
23
+
24
+ 새로운 컬러셋을 추가고자 할 때는 미리보기 Bar를 더블클릭한다.
25
+ 컬러셋을 제거하고자 할 때는 컬러셋 마커를 아래방향으로 드래깅한다.
26
+ 컬러셋의 위치를 옮기고자 할 때는, 컬러셋 마커를 좌우로 드래깅하여 이동시키거나,
27
+ 옮기고자하는 컬러셋 마커를 마우스로 선택하고, 포지션 입력 에디터에서 직접 수정한다.
28
+ 컬러셋의 색상을 바꾸고자 할 때는, 컬러셋 마커를 더블클릭하여 컬러파레트를 팝업시켜서 색상을 선택하거나, 색상 입력 에디터에서 직접 색상을 수정할 수 있다.
29
+
30
+ Example:
31
+
32
+ <ox-input-color-stops type="gradient" .value=${gradient.colorStops}>
33
+ </ox-input-color-stops>
34
+ */
35
+ @customElement('ox-input-color-stops')
36
+ export class OxInputColorStops extends OxFormField {
37
+ static styles = css`
38
+ :host {
39
+ display: grid;
40
+ grid-template-columns: repeat(10, 1fr);
41
+ grid-gap: 0;
42
+ grid-auto-rows: minmax(0, auto);
43
+ }
44
+
45
+ #color-stops {
46
+ grid-column: 1 / 11;
47
+ grid-row: 1;
48
+
49
+ clear: both;
50
+ margin-bottom: -3px;
51
+ }
52
+
53
+ #colorbar {
54
+ width: 95%;
55
+ height: 12px;
56
+ margin: auto;
57
+ margin-bottom: 25px;
58
+ border: 1px solid #ccc;
59
+ }
60
+
61
+ #markers {
62
+ position: relative;
63
+ top: 30px;
64
+ }
65
+
66
+ #markers div {
67
+ width: 10px;
68
+ height: 10px;
69
+ margin-top: -15px;
70
+ position: absolute;
71
+ border: 2px solid #fff;
72
+ cursor: pointer;
73
+ -webkit-box-shadow: 1px 1px 1px 0px rgba(0, 0, 0, 0.2);
74
+ -moz-box-shadow: 1px 1px 1px 0px rgba(0, 0, 0, 0.2);
75
+ box-shadow: 1px 1px 1px 0px rgba(0, 0, 0, 0.2);
76
+ }
77
+
78
+ #markers div::before {
79
+ border-bottom: 6px solid #fff;
80
+ border-left: 7px solid transparent;
81
+ border-right: 7px solid transparent;
82
+ content: '';
83
+ width: 0;
84
+ height: 0;
85
+ left: -2px;
86
+ position: absolute;
87
+ top: -8px;
88
+ }
89
+
90
+ #markers div[focused] {
91
+ border-color: var(--things-editor-colorbar-marker-focused-color, #585858);
92
+ }
93
+
94
+ #markers div[focused]:before {
95
+ border-bottom: 7px solid var(--things-editor-colorbar-marker-focused-color, #585858);
96
+ }
97
+
98
+ .icon-only-label {
99
+ background: url(/assets/images/icon-properties-label.png) no-repeat;
100
+ width: 30px;
101
+ height: 24px;
102
+ }
103
+
104
+ .icon-only-label.color {
105
+ grid-column: 1 / 2;
106
+ grid-row: 2;
107
+
108
+ background-position: 70% -498px;
109
+ float: left;
110
+ margin-top: 0;
111
+ }
112
+
113
+ .icon-only-label.position {
114
+ grid-column: 7 / 8;
115
+ grid-row: 2;
116
+
117
+ background-position: 70% -797px;
118
+ float: left;
119
+ margin-top: 0;
120
+ }
121
+
122
+ ox-input-color {
123
+ grid-column: 2 / 7;
124
+ grid-row: 2;
125
+ }
126
+
127
+ input[type='number'] {
128
+ grid-column: 8 / 11;
129
+ grid-row: 2;
130
+ border: 1px solid rgba(0, 0, 0, 0.2);
131
+ }
132
+ `
133
+
134
+ /**
135
+ * `type`은 color-stop bar의 표시 방법을 의미한다.
136
+ * - 'solid' : 컬러스톱위치에서 다음 컬러스톱까지 solid color로 채운다.
137
+ * - 'gradient' : 컬러스톱위치에서 다음 컬러스톱까지 gradient color로 채운다.
138
+ */
139
+ @property({ type: String }) type: 'solid' | 'gradient' = 'solid'
140
+ /**
141
+ * `min`은 color-stop bar의 위치값 범위의 최소값을 의미한다.
142
+ */
143
+ @property({ type: Number }) min: number = 0
144
+ /**
145
+ * `max`은 color-stop bar의 위치값 범위의 최대값을 의미한다.
146
+ */
147
+ @property({ type: Number }) max: number = 1
148
+ /**
149
+ * `value`은 color-stops에 의해 만들어진 color-stop 배열을 유지한다.
150
+ */
151
+ @property({ type: Array }) value?: ColorStop[]
152
+ @property({ type: Object }) focused: any
153
+
154
+ @query('#colorbar') colorbar!: HTMLElement
155
+ @query('#color-editor') colorEditor!: OxInputColor
156
+
157
+ private _dragImage?: HTMLImageElement
158
+
159
+ connectedCallback() {
160
+ super.connectedCallback()
161
+
162
+ this._dragImage = new Image()
163
+ this._dragImage.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
164
+ }
165
+
166
+ firstUpdated() {
167
+ window.addEventListener('resize', () => {
168
+ this.requestUpdate()
169
+ })
170
+ }
171
+
172
+ updated(changes: PropertyValues<this>) {
173
+ var needRerenderColorBar = false
174
+
175
+ if (changes.has('value') && this.value instanceof Array) {
176
+ var oldValue = changes.get('value')
177
+ if (
178
+ this.focused &&
179
+ (!oldValue ||
180
+ this.value.findIndex(v => v.position == this.focused.position && v.color == this.focused.color) == -1)
181
+ ) {
182
+ /* 이전 값이 없었던 경우에 focused를 클리어시킨다.
183
+ * 이전 값이 있던 경우에도, focused는 이 에디터 내부에서만 선택될 수 있으며, 수정될 수 있으므로 동일한 포지션을 갖는 value가 없으면, 새로운 에디터가 시작된 것으로 판단하여 focused를 클리어시킨다.
184
+ */
185
+ this.focused = null
186
+ }
187
+
188
+ if (!deepEquals(oldValue, this.value)) {
189
+ needRerenderColorBar = true
190
+ }
191
+ }
192
+
193
+ if (needRerenderColorBar || changes.has('min') || changes.has('max')) {
194
+ if (!this.value) {
195
+ this.value = [
196
+ { color: 'white', position: this.min },
197
+ { color: 'white', position: this.max }
198
+ ]
199
+ }
200
+
201
+ this._renderColorBar(this.min, this.max, this.type)
202
+ this.requestUpdate()
203
+ }
204
+ }
205
+
206
+ render() {
207
+ return html`
208
+ <div id="color-stops">
209
+ <div id="colorbar" @dblclick=${(e: MouseEvent) => this._onDblClickColorbar(e)}>
210
+ <div
211
+ id="markers"
212
+ @dblclick=${(e: MouseEvent) => this._onDblClickMarkers(e)}
213
+ @mousedown=${(e: MouseEvent) => this._onMouseDown(e)}
214
+ @dragstart=${(e: DragEvent) => this._onDragStart(e)}
215
+ @drag=${this._throttled(100, this._onDrag.bind(this))}
216
+ @dragend=${(e: DragEvent) => this._onDragEnd(e)}
217
+ >
218
+ ${this._refinedValue(this.value).map(
219
+ (item, index) => html`
220
+ <div
221
+ .style="background-color:${item.color};margin-left:${this._calculatePosition(
222
+ item.position,
223
+ this.min,
224
+ this.max
225
+ )}px;"
226
+ marker-index=${index}
227
+ draggable="true"
228
+ ></div>
229
+ `
230
+ )}
231
+ </div>
232
+ </div>
233
+ </div>
234
+
235
+ <label class="icon-only-label color"></label>
236
+ <ox-input-color
237
+ id="color-editor"
238
+ .value=${this.focused && this.focused.color}
239
+ @change=${(e: Event) => this._onChangeSubComponent(e)}
240
+ >
241
+ </ox-input-color>
242
+
243
+ <label class="icon-only-label position"></label>
244
+ <input
245
+ type="number"
246
+ id="color-position"
247
+ .value=${this.focused && this.focused.position}
248
+ @change=${(e: Event) => this._onChangeSubComponent(e)}
249
+ step="0.01"
250
+ />
251
+ `
252
+ }
253
+
254
+ _refinedValue(value: any) {
255
+ return value instanceof Array ? value : []
256
+ }
257
+
258
+ _setFocused(index: number) {
259
+ if (this.focused && this.focused.index === index) {
260
+ return
261
+ }
262
+
263
+ var marker = this.renderRoot.querySelector(`#markers div[marker-index='${index}']`) as HTMLElement
264
+ var olds = this.renderRoot.querySelectorAll('#markers div[focused]')
265
+ olds.length > 0 && olds.forEach(old => old.removeAttribute('focused'))
266
+ marker && marker.setAttribute('focused', '')
267
+
268
+ if (!marker) {
269
+ this.focused = null
270
+ return
271
+ }
272
+
273
+ var colorStop = this.value![index]
274
+
275
+ this._changeFocused({
276
+ index: index,
277
+ color: colorStop.color,
278
+ position: Math.max(this.min, Math.min(colorStop.position, this.max))
279
+ })
280
+ }
281
+
282
+ _changeFocused(focused: any) {
283
+ if (!focused) {
284
+ this._setFocused(-1) // clear focused marker
285
+
286
+ return
287
+ }
288
+
289
+ this.focused = focused
290
+
291
+ this.value = this.value!.map((colorStop, index): ColorStop => {
292
+ if (index != focused.index) {
293
+ return colorStop
294
+ }
295
+
296
+ return {
297
+ color: focused.color,
298
+ position: focused.position
299
+ }
300
+ }).sort((a: ColorStop, b: ColorStop) => {
301
+ return b.position < a.position ? 1 : -1
302
+ })
303
+
304
+ var colorStop = this.value[focused.index]
305
+
306
+ if (focused.position != colorStop.position || focused.color != colorStop.color) {
307
+ var index = -1
308
+ for (var i = 0; i < this.value.length; i++) {
309
+ colorStop = this.value[i]
310
+ if (focused.position == colorStop.position && focused.color == colorStop.color) {
311
+ index = i
312
+ break
313
+ }
314
+ }
315
+
316
+ this._setFocused(index)
317
+ }
318
+ }
319
+
320
+ _renderColorBar(min: number, max: number, type: 'solid' | 'gradient') {
321
+ var value = this._refinedValue(this.value)
322
+ var gradient = ''
323
+
324
+ if (value instanceof Array && value.length > 0) {
325
+ if (this.type == 'gradient') {
326
+ var stopsStrings = (value || []).map(function (stop) {
327
+ var position = (stop.position - min) / (max - min)
328
+ return `${stop.color} ${position * 100}%`
329
+ })
330
+ } else {
331
+ var stops = value || []
332
+ var last: ColorStop | undefined
333
+ var last_position = 0
334
+ var stopsStrings = stops.map(function (stop) {
335
+ var stop_position = (stop.position - min) / (max - min)
336
+ if (last) {
337
+ last_position = (last.position - min) / (max - min)
338
+ var step = `${stop.color} ${last_position * 100}%, ${stop.color} ${stop_position * 100}%`
339
+ } else {
340
+ var step = `${stop.color} ${stop_position * 100}%`
341
+ }
342
+ last = stop
343
+ return step
344
+ })
345
+ if (last) {
346
+ last_position = (last.position - min) / (max - min)
347
+ stopsStrings.push(`${last.color} ${last_position * 100}%, white ${last_position * 100}%, white 100%`)
348
+ }
349
+ }
350
+
351
+ gradient = stopsStrings.join(',')
352
+ } else {
353
+ gradient = 'black 0%, black 100%'
354
+ }
355
+
356
+ this.colorbar!.style.background = `linear-gradient(to right, ${gradient})`
357
+ /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
358
+ }
359
+
360
+ _onChangeSubComponent(e: Event) {
361
+ var element = e.target as HTMLInputElement
362
+ var id = element.id
363
+
364
+ if (!this.focused) {
365
+ return
366
+ }
367
+
368
+ switch (id) {
369
+ case 'color-editor':
370
+ this._changeFocused({
371
+ ...this.focused,
372
+ color: element.value
373
+ })
374
+ break
375
+ case 'color-position':
376
+ this._changeFocused({
377
+ ...this.focused,
378
+ position: Math.max(this.min, Math.min(Number(element.value), this.max))
379
+ })
380
+ break
381
+ }
382
+
383
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
384
+ }
385
+
386
+ _onDblClickColorbar(e: MouseEvent) {
387
+ /* 마커를 클릭한 경우를 걸러낸다. */
388
+ if (e.target !== this.colorbar) return
389
+
390
+ var width = this.colorbar.offsetWidth
391
+ var position = this.min + (this.max - this.min) * (e.offsetX / width)
392
+ var colorStops = this.value ? this.value.slice() : []
393
+
394
+ for (var i = 0; i < colorStops.length; i++) {
395
+ if (colorStops[i].position > position) break
396
+ }
397
+
398
+ colorStops.splice(i, 0, {
399
+ position: position,
400
+ color: '#fff'
401
+ })
402
+
403
+ this.value = colorStops
404
+
405
+ this.focused = null
406
+ this._setFocused(i)
407
+
408
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
409
+ }
410
+
411
+ _onDblClickMarkers(e: MouseEvent) {
412
+ this.colorEditor.showPicker()
413
+ }
414
+
415
+ _onMouseDown(e: MouseEvent) {
416
+ var marker = e.target as HTMLElement
417
+ var index = marker.getAttribute('marker-index')
418
+
419
+ this._setFocused(Number(index))
420
+ }
421
+
422
+ private dragstart: { position: number; x: number; y: number } = { position: 0, x: 0, y: 0 }
423
+
424
+ _onDragStart(e: DragEvent) {
425
+ /* drag 시에 ghost image를 보이지 않게 하려고 함 */
426
+ e.dataTransfer?.setDragImage(this._dragImage!, 0, 0)
427
+
428
+ this.dragstart = {
429
+ position: this.focused.position,
430
+ x: e.clientX,
431
+ y: e.clientY
432
+ }
433
+ }
434
+
435
+ // TODO onDrag 이벤트가 계속 발생하므로 처리하는 성능 저하됨. 그래서 throttling 하도록 함
436
+ _throttled(delay: number, fn: (...args: any[]) => any) {
437
+ let lastCall = 0
438
+ return function (...args: any[]) {
439
+ const now = new Date().getTime()
440
+ if (now - lastCall < delay) {
441
+ return
442
+ }
443
+ lastCall = now
444
+ return fn(...args)
445
+ }
446
+ }
447
+
448
+ _onDrag(e: DragEvent) {
449
+ if (e.clientX <= 0) {
450
+ return
451
+ }
452
+
453
+ var width = this.colorbar.offsetWidth
454
+ var position = this.dragstart.position + ((e.clientX - this.dragstart.x) / width) * (this.max - this.min)
455
+
456
+ if (position != this.focused.position) {
457
+ this._changeFocused({
458
+ ...this.focused,
459
+ position: Math.max(this.min, Math.min(position, this.max))
460
+ })
461
+
462
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
463
+ }
464
+ }
465
+
466
+ _onDragEnd(e: DragEvent) {
467
+ if (e.clientY - this.dragstart.y > 40) {
468
+ this.value!.splice(this.focused.index, 1)
469
+ this.value = this.value!.slice()
470
+
471
+ this._setFocused(-1)
472
+
473
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
474
+ }
475
+ }
476
+
477
+ _calculatePosition(position: number, min: number, max: number) {
478
+ /* TODO 7 ==> 마커 폭의 절반으로 계산해야함. */
479
+ var calculated = position
480
+
481
+ if (calculated > this.max) calculated = this.max
482
+ else if (calculated < this.min) calculated = this.min
483
+
484
+ var width = (this.colorbar && this.colorbar.offsetWidth) || 0
485
+
486
+ return ((calculated - this.min) / (this.max - this.min)) * width - 7
487
+ }
488
+
489
+ protected appendFormData({ formData }: FormDataEvent): void {
490
+ if (!this.name) return
491
+
492
+ const value = this.value
493
+
494
+ formData.append(
495
+ this.name!,
496
+ typeof value === 'string' ? value : value === undefined || value === null ? '' : JSON.stringify(value)
497
+ )
498
+ }
499
+ }