@operato/input 1.0.0-alpha.3 → 1.0.0-alpha.32

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 (111) hide show
  1. package/CHANGELOG.md +252 -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-table.html +39 -0
  18. package/demo/index-value-map.html +80 -0
  19. package/demo/index-value-ranges.html +80 -0
  20. package/demo/index.html +23 -54
  21. package/dist/src/index.d.ts +21 -11
  22. package/dist/src/index.js +21 -11
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/ox-checkbox.js +1 -1
  25. package/dist/src/ox-checkbox.js.map +1 -1
  26. package/dist/src/ox-input-code.d.ts +4 -4
  27. package/dist/src/ox-input-code.js +8 -8
  28. package/dist/src/ox-input-code.js.map +1 -1
  29. package/dist/src/ox-input-color-gradient.d.ts +26 -0
  30. package/dist/src/ox-input-color-gradient.js +318 -0
  31. package/dist/src/ox-input-color-gradient.js.map +1 -0
  32. package/dist/src/ox-input-color-stops.d.ts +71 -0
  33. package/dist/src/ox-input-color-stops.js +445 -0
  34. package/dist/src/ox-input-color-stops.js.map +1 -0
  35. package/dist/src/ox-input-color.d.ts +176 -0
  36. package/dist/src/ox-input-color.js +298 -0
  37. package/dist/src/ox-input-color.js.map +1 -0
  38. package/dist/src/ox-input-crontab.d.ts +23 -0
  39. package/dist/src/ox-input-crontab.js +560 -0
  40. package/dist/src/ox-input-crontab.js.map +1 -0
  41. package/dist/src/ox-input-data.d.ts +2 -2
  42. package/dist/src/ox-input-data.js +2 -2
  43. package/dist/src/ox-input-data.js.map +1 -1
  44. package/dist/src/ox-input-file.d.ts +2 -0
  45. package/dist/src/ox-input-file.js +6 -1
  46. package/dist/src/ox-input-file.js.map +1 -1
  47. package/dist/src/ox-input-layout/ox-input-card-layout.d.ts +4 -0
  48. package/dist/src/ox-input-layout/ox-input-card-layout.js +57 -0
  49. package/dist/src/ox-input-layout/ox-input-card-layout.js.map +1 -0
  50. package/dist/src/ox-input-layout/ox-input-grid-layout.d.ts +4 -0
  51. package/dist/src/ox-input-layout/ox-input-grid-layout.js +63 -0
  52. package/dist/src/ox-input-layout/ox-input-grid-layout.js.map +1 -0
  53. package/dist/src/ox-input-layout/ox-input-layout.d.ts +5 -0
  54. package/dist/src/ox-input-layout/ox-input-layout.js +73 -0
  55. package/dist/src/ox-input-layout/ox-input-layout.js.map +1 -0
  56. package/dist/src/ox-input-multiple-colors.d.ts +28 -0
  57. package/dist/src/ox-input-multiple-colors.js +113 -0
  58. package/dist/src/ox-input-multiple-colors.js.map +1 -0
  59. package/dist/src/ox-input-options.d.ts +22 -0
  60. package/dist/src/ox-input-options.js +137 -0
  61. package/dist/src/ox-input-options.js.map +1 -0
  62. package/dist/src/ox-input-partition-keys.d.ts +36 -0
  63. package/dist/src/ox-input-partition-keys.js +203 -0
  64. package/dist/src/ox-input-partition-keys.js.map +1 -0
  65. package/dist/src/ox-input-range.d.ts +4 -0
  66. package/dist/src/ox-input-range.js +161 -0
  67. package/dist/src/ox-input-range.js.map +1 -0
  68. package/dist/src/{ox-input-id.d.ts → ox-input-scene-component-id.d.ts} +0 -0
  69. package/dist/src/{ox-input-id.js → ox-input-scene-component-id.js} +2 -2
  70. package/dist/src/ox-input-scene-component-id.js.map +1 -0
  71. package/dist/src/ox-input-stack.d.ts +1 -1
  72. package/dist/src/ox-input-stack.js +1 -1
  73. package/dist/src/ox-input-stack.js.map +1 -1
  74. package/dist/src/ox-input-table.d.ts +8 -0
  75. package/dist/src/ox-input-table.js +379 -0
  76. package/dist/src/ox-input-table.js.map +1 -0
  77. package/dist/src/ox-input-value-map.d.ts +41 -0
  78. package/dist/src/ox-input-value-map.js +279 -0
  79. package/dist/src/ox-input-value-map.js.map +1 -0
  80. package/dist/src/ox-input-value-ranges.d.ts +41 -0
  81. package/dist/src/ox-input-value-ranges.js +298 -0
  82. package/dist/src/ox-input-value-ranges.js.map +1 -0
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +25 -7
  85. package/src/index.ts +21 -11
  86. package/src/ox-checkbox.ts +1 -1
  87. package/src/ox-input-code.ts +9 -10
  88. package/src/ox-input-color-gradient.ts +343 -0
  89. package/src/ox-input-color-stops.ts +499 -0
  90. package/src/ox-input-color.ts +323 -0
  91. package/src/ox-input-crontab.ts +560 -0
  92. package/src/ox-input-data.ts +5 -5
  93. package/src/ox-input-file.ts +8 -3
  94. package/src/ox-input-layout/ox-input-card-layout.ts +58 -0
  95. package/src/ox-input-layout/ox-input-grid-layout.ts +64 -0
  96. package/src/ox-input-layout/ox-input-layout.ts +77 -0
  97. package/src/ox-input-multiple-colors.ts +113 -0
  98. package/src/ox-input-options.ts +165 -0
  99. package/src/ox-input-partition-keys.ts +242 -0
  100. package/src/ox-input-range.ts +147 -0
  101. package/src/{ox-input-id.ts → ox-input-scene-component-id.ts} +1 -1
  102. package/src/ox-input-stack.ts +1 -1
  103. package/src/ox-input-table.ts +404 -0
  104. package/src/{ox-input-keyvalues.ts.ing → ox-input-value-map.ts} +125 -94
  105. package/src/ox-input-value-ranges.ts +325 -0
  106. package/translations/en.json +1 -0
  107. package/translations/ko.json +1 -0
  108. package/translations/ms.json +1 -0
  109. package/translations/zh.json +1 -0
  110. package/dist/src/ox-input-id.js.map +0 -1
  111. package/src/ox-input-ranges.ts.ing +0 -292
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { LitElement, PropertyValues, css, html } from 'lit'
6
+ import { customElement, property, state } from 'lit/decorators.js'
7
+
8
+ @customElement('ox-input-grid-layout')
9
+ class OxInputGridLayout extends LitElement {
10
+ static styles = css`
11
+ :host {
12
+ display: inline-block;
13
+ }
14
+ `
15
+
16
+ @property({ type: Object }) value: any
17
+ @property({ type: String }) direction: 'row' | 'column' = 'row'
18
+
19
+ firstUpdated() {
20
+ this.renderRoot.addEventListener('change', this._onValueChange.bind(this))
21
+ }
22
+
23
+ updated(changes: PropertyValues<this>) {
24
+ if (changes.has('value')) {
25
+ let { direction = 'row' } = this.value || {}
26
+
27
+ this.direction = direction
28
+ }
29
+
30
+ if (changes.has('value')) {
31
+ }
32
+ }
33
+
34
+ render() {
35
+ return html`
36
+ <label>direction</label>
37
+ <select value-key="direction" .value=${this.direction}>
38
+ <option value="row" selected>row</option>
39
+ <option value="column">column</option>
40
+ </select>
41
+ `
42
+ }
43
+
44
+ _onValueChange(e: Event) {
45
+ var element = e.target as HTMLSelectElement
46
+ var key = element.getAttribute('value-key')
47
+
48
+ if (!key) {
49
+ return
50
+ }
51
+
52
+ switch (key) {
53
+ case 'direction':
54
+ this.direction = element.value as 'row' | 'column'
55
+ default:
56
+ }
57
+
58
+ this.value = {
59
+ direction: this.direction
60
+ }
61
+
62
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
63
+ }
64
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import './things-grid-layout'
6
+ import './things-card-layout'
7
+
8
+ import { LitElement, PropertyValues, html } from 'lit'
9
+ import { customElement, property, state } from 'lit/decorators.js'
10
+
11
+ // import './things-linear-horizontal-layout'
12
+ // import './things-linear-vertical-layout'
13
+
14
+ const layouts = ['absolute', 'card', 'grid', 'linear-horizontal', 'linear-vertical', 'table']
15
+
16
+ @customElement('ox-input-layout')
17
+ class OxInputLayout extends LitElement {
18
+ @property({ type: Object }) value: any = {}
19
+ @property({ type: String }) layout:
20
+ | ''
21
+ | 'absolute'
22
+ | 'card'
23
+ | 'grid'
24
+ | 'linear-horizontal'
25
+ | 'linear-vertical'
26
+ | 'table' = ''
27
+ @property({ type: Object }) options: any = {}
28
+
29
+ firstUpdated() {
30
+ this.renderRoot.addEventListener('change', this._onValueChange.bind(this))
31
+ }
32
+
33
+ updated(changes: PropertyValues<this>) {
34
+ if (changes.has('value')) {
35
+ this.layout = this.value.layout
36
+ this.options = this.value.options
37
+ }
38
+ }
39
+
40
+ render() {
41
+ return html`
42
+ <div>
43
+ <select value-key="layout" .value=${this.layout}>
44
+ <option value="" selected></option>
45
+ ${layouts.map(layout => {
46
+ return html` <option value=${layout}>${layout}</option> `
47
+ })}
48
+ </select>
49
+
50
+ ${this.layout == 'grid'
51
+ ? html` <things-grid-layout value-key="options" .value=${this.options}></things-grid-layout> `
52
+ : this.layout == 'card'
53
+ ? html` <things-card-layout value-key="options" .value=${this.options}></things-card-layout> `
54
+ : html``}
55
+ </div>
56
+ `
57
+ }
58
+
59
+ _onValueChange(e: Event) {
60
+ var element = e.target as HTMLElement
61
+ var key = element.getAttribute('value-key')
62
+
63
+ if (!key) {
64
+ return
65
+ }
66
+
67
+ //@ts-ignore
68
+ this[key] = element.value
69
+
70
+ this.value = {
71
+ layout: this.layout,
72
+ options: this.options
73
+ }
74
+
75
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
76
+ }
77
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import './ox-input-color.js'
6
+
7
+ import { css, html } from 'lit'
8
+ import { customElement, property, query, queryAll } from 'lit/decorators.js'
9
+
10
+ import { OxFormField } from './ox-form-field.js'
11
+ import { OxInputColor } from './ox-input-color.js'
12
+
13
+ /**
14
+ 색상 배열을 편집하는 컴포넌트이다.
15
+
16
+ 새로운 색상을 추가하고자 할 때는 `+` 버튼을 클릭한다.<br />
17
+ 색상을 제거하고자 할 때는 `-` 버튼을 클릭한다.<br />
18
+
19
+ Example:
20
+
21
+ <ox-input-multiple-colors values=${values}>
22
+ </ox-input-multiple-colors>
23
+ */
24
+
25
+ @customElement('ox-input-multiple-colors')
26
+ export class OxInputMultipleColors extends OxFormField {
27
+ static styles = css`
28
+ :host {
29
+ display: inline-block;
30
+ }
31
+
32
+ #colors-container > div {
33
+ display: grid;
34
+ grid-template-columns: 22px 1fr 22px;
35
+ grid-gap: 5px;
36
+ align-items: center;
37
+ justify-content: left;
38
+ }
39
+
40
+ ox-input-color {
41
+ height: 25px;
42
+ width: 100%;
43
+ }
44
+
45
+ input[type='button'] {
46
+ width: 22px;
47
+ height: 25px;
48
+ border: 1px solid rgba(0, 0, 0, 0.15);
49
+ padding-top: 0px;
50
+ padding-bottom: 2px;
51
+ background-color: #f1f2f4;
52
+ color: #8f9192;
53
+ font-size: 16px;
54
+ }
55
+ `
56
+
57
+ @property({ type: Array }) value: string[] = []
58
+
59
+ @query('#colors-container') colorsContainer!: HTMLDivElement
60
+ @queryAll('ox-input-color') colors!: NodeListOf<OxInputColor>
61
+
62
+ firstUpdated() {
63
+ this.renderRoot.addEventListener('change', this._onValueChanged.bind(this))
64
+ }
65
+
66
+ render() {
67
+ return html`
68
+ <div id="colors-container">
69
+ ${(this.value || []).map(
70
+ (item, index) => html`
71
+ <div>
72
+ <input type="button" value="+" @click=${() => this._appendEditorColor()} data-index=${index} />
73
+
74
+ <ox-input-color .value=${item}> </ox-input-color>
75
+
76
+ ${(this.value || []).length > 1
77
+ ? html`
78
+ <input
79
+ type="button"
80
+ value="-"
81
+ @click=${(e: Event) => this._removeEditorColor(e)}
82
+ data-index=${index}
83
+ />
84
+ `
85
+ : html``}
86
+ </div>
87
+ `
88
+ )}
89
+ </div>
90
+ `
91
+ }
92
+
93
+ _onValueChanged() {
94
+ this.value = Array.from(this.colors).map(color => color.value!)
95
+ }
96
+
97
+ _appendEditorColor() {
98
+ this.value = [...this.value, 'black']
99
+
100
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
101
+ }
102
+
103
+ _removeEditorColor(e: Event) {
104
+ var values = []
105
+ for (var i = 0; i < this.value.length; i++) {
106
+ if (i == Number((e.target as HTMLElement).dataset.index)) continue
107
+ else values.push(this.value[i])
108
+ }
109
+
110
+ this.value = values
111
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
112
+ }
113
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { css, html } from 'lit'
6
+ import { customElement, property } from 'lit/decorators.js'
7
+
8
+ import { OxFormField } from './ox-form-field'
9
+
10
+ type Option = { text: string; value: string }
11
+
12
+ @customElement('ox-input-options')
13
+ export class OxInputOptions extends OxFormField {
14
+ static styles = css`
15
+ div {
16
+ display: grid;
17
+ grid-template-columns: repeat(10, 1fr);
18
+ grid-gap: 5px;
19
+ grid-auto-rows: minmax(24px, auto);
20
+ }
21
+
22
+ input[data-text] {
23
+ grid-column: span 5;
24
+ }
25
+
26
+ input[data-value] {
27
+ grid-column: span 4;
28
+ }
29
+
30
+ button {
31
+ grid-column: span 1;
32
+ }
33
+ `
34
+
35
+ @property({ type: Array }) value: Option[] = []
36
+
37
+ firstUpdated() {
38
+ this.renderRoot.addEventListener('change', this._onChange.bind(this))
39
+ }
40
+
41
+ render() {
42
+ const options = this.value instanceof Array ? this.value : []
43
+
44
+ return html`
45
+ ${(options || []).map(
46
+ item => html`
47
+ <div data-record="">
48
+ <input type="text" data-text="" placeholder="text" .value=${item.text} />
49
+ <input type="text" data-value="" placeholder="value" .value=${item.value} />
50
+ <button class="record-action" @click=${(e: MouseEvent) => this._delete(e)} tabindex="-1">-</button>
51
+ </div>
52
+ `
53
+ )}
54
+
55
+ <div data-record-new="">
56
+ <input type="text" data-text="" placeholder="text" value="" />
57
+ <input type="text" data-value="" placeholder="value" value="" @change=${(e: Event) => this._add()} />
58
+ <button class="record-action" @click=${(e: MouseEvent) => this._add()} tabindex="-1">+</button>
59
+ </div>
60
+ `
61
+ }
62
+
63
+ private _changingNow: boolean = false
64
+
65
+ _onChange(e: Event) {
66
+ if (this._changingNow) return
67
+
68
+ this._changingNow = true
69
+
70
+ var input = e.target as HTMLInputElement
71
+ var value = input.value
72
+
73
+ var div = input.parentElement
74
+
75
+ if (div && div.hasAttribute('data-record')) {
76
+ var dataList = div.querySelectorAll('[data-value]:not([hidden])') as NodeListOf<HTMLInputElement>
77
+
78
+ for (var i = 0; i < dataList.length; i++) {
79
+ if (dataList[i] !== input) {
80
+ dataList[i].value = value || ''
81
+ }
82
+ }
83
+ }
84
+
85
+ if (div && div.hasAttribute('data-record')) this._build(true)
86
+ else if (div && div.hasAttribute('data-record-new') && input.hasAttribute('data-value')) this._add()
87
+
88
+ e.stopPropagation()
89
+
90
+ this._changingNow = false
91
+ }
92
+
93
+ _build(includeNewRecord?: any) {
94
+ if (includeNewRecord) {
95
+ var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]') as NodeListOf<HTMLElement>
96
+ } else {
97
+ var records = this.renderRoot.querySelectorAll('[data-record]') as NodeListOf<HTMLElement>
98
+ }
99
+
100
+ var newoptions: Option[] = []
101
+
102
+ for (var i = 0; i < records.length; i++) {
103
+ var record = records[i]
104
+
105
+ var text = (record.querySelector('[data-text]') as HTMLInputElement).value
106
+ var inputs = record.querySelectorAll('[data-value]:not([style*="display: none"])') as NodeListOf<HTMLInputElement>
107
+ if (!inputs || inputs.length == 0) continue
108
+
109
+ var input = inputs[inputs.length - 1]
110
+ var value = input.value
111
+
112
+ if (text) newoptions.push({ text: text, value: value || text })
113
+ }
114
+
115
+ this.value = newoptions
116
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
117
+ }
118
+
119
+ sort() {
120
+ var sorter = function (a: Option, b: Option) {
121
+ return b.text < a.text ? 1 : -1
122
+ }
123
+
124
+ this.value = [...this.value.sort(sorter)]
125
+
126
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
127
+ }
128
+
129
+ _add() {
130
+ this._build(true)
131
+
132
+ var inputs = this.renderRoot.querySelectorAll(
133
+ '[data-record-new] input:not([style*="display: none"])'
134
+ ) as NodeListOf<HTMLInputElement>
135
+
136
+ for (var i = 0; i < inputs.length; i++) {
137
+ let input = inputs[i]
138
+ input.value = ''
139
+ }
140
+
141
+ inputs[0].focus()
142
+ }
143
+
144
+ _delete(e: Event) {
145
+ const record = (e.target as HTMLElement).parentElement
146
+ const input = record && (record.querySelector('[data-text]') as HTMLInputElement)
147
+
148
+ if (input) {
149
+ input.value = ''
150
+ }
151
+
152
+ this._build()
153
+ }
154
+
155
+ protected appendFormData({ formData }: FormDataEvent): void {
156
+ if (!this.name) return
157
+
158
+ const value = this.value
159
+
160
+ formData.append(
161
+ this.name!,
162
+ typeof value === 'string' ? value : value === undefined || value === null ? '' : JSON.stringify(value)
163
+ )
164
+ }
165
+ }
@@ -0,0 +1,242 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { css, html } from 'lit'
6
+ import { customElement, property, queryAll } from 'lit/decorators.js'
7
+
8
+ import { OxFormField } from './ox-form-field'
9
+
10
+ type PartitionKeys = { [key: string]: any }
11
+ type ArrayedPartitionKeys = { key: string; value: any }
12
+
13
+ /**
14
+ key-value map for partitions editor element
15
+
16
+ Example:
17
+
18
+ <ox-input-partition-keys
19
+ value=${map}
20
+ </ox-input-partition-keys>
21
+ */
22
+ @customElement('ox-input-partition-keys')
23
+ export class OxInputPartitionKeys extends OxFormField {
24
+ static styles = css`
25
+ :host {
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-content: center;
29
+
30
+ width: 100%;
31
+ overflow: hidden;
32
+ border: 1px solid #ccc;
33
+ }
34
+
35
+ div {
36
+ display: flex;
37
+ flex-flow: row nowrap;
38
+ align-items: center;
39
+
40
+ border-bottom: 1px solid #c0c0c0;
41
+ }
42
+
43
+ div:last-child {
44
+ border-bottom: none;
45
+ }
46
+
47
+ div > * {
48
+ min-width: 0px;
49
+ margin: 2px;
50
+ padding: 0;
51
+ }
52
+
53
+ button {
54
+ width: 20px;
55
+ text-align: center;
56
+ }
57
+
58
+ input {
59
+ flex: 1;
60
+ }
61
+ `
62
+
63
+ @property({ type: Object }) value: PartitionKeys = {}
64
+
65
+ private _changingNow: boolean = false
66
+
67
+ firstUpdated() {
68
+ this.renderRoot.addEventListener('change', this._onChange.bind(this))
69
+ }
70
+
71
+ render() {
72
+ const value = !this.value || typeof this.value !== 'object' ? {} : this.value
73
+
74
+ return html`
75
+ ${this._toArray(value).map(
76
+ item => html`
77
+ <div data-record>
78
+ <input type="text" data-key placeholder="key" .value=${item.key} />
79
+ <input type="text" data-value placeholder="value" .value=${item.value} list="value-template" />
80
+ <button class="record-action" @click=${(e: MouseEvent) => this._delete(e)} tabindex="-1">-</button>
81
+ <button class="record-action" @click=${(e: MouseEvent) => this._up(e)} tabindex="-1">↑</button>
82
+ <button class="record-action" @click=${(e: MouseEvent) => this._down(e)} tabindex="-1">↓</button>
83
+ </div>
84
+ `
85
+ )}
86
+
87
+ <div data-record-new>
88
+ <input type="text" data-key placeholder="key" value="" />
89
+ <input type="text" data-value placeholder="value" value="" list="value-template" />
90
+ <button class="record-action" @click=${(e: MouseEvent) => this._add()} tabindex="-1">+</button>
91
+ </div>
92
+
93
+ <datalist id="value-template">
94
+ <option value="%%YY">year</option>
95
+ <option value="%%MM">month</option>
96
+ <option value="%%DD">day</option>
97
+ </datalist>
98
+ `
99
+ }
100
+
101
+ _onChange(e: Event) {
102
+ if (this._changingNow) {
103
+ return
104
+ }
105
+
106
+ this._changingNow = true
107
+
108
+ const input = e.target as HTMLInputElement
109
+ var value = input.value
110
+
111
+ const record = (e.target as Element).closest('[data-record],[data-record-new]') as HTMLElement
112
+
113
+ if (record.hasAttribute('data-record')) {
114
+ this._build()
115
+ } else if (record.hasAttribute('data-record-new') && input.hasAttribute('data-value')) {
116
+ this._add()
117
+ }
118
+
119
+ this._changingNow = false
120
+ }
121
+
122
+ _build(includeNewRecord?: boolean) {
123
+ if (includeNewRecord) {
124
+ var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]') as NodeListOf<HTMLElement>
125
+ } else {
126
+ var records = this.renderRoot.querySelectorAll('[data-record]') as NodeListOf<HTMLElement>
127
+ }
128
+
129
+ var newmap: PartitionKeys = {}
130
+
131
+ for (var i = 0; i < records.length; i++) {
132
+ var record = records[i]
133
+
134
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
135
+ const inputs = record.querySelectorAll(
136
+ '[data-value]:not([style*="display: none"])'
137
+ ) as NodeListOf<HTMLInputElement>
138
+
139
+ if (!inputs || inputs.length == 0) {
140
+ continue
141
+ }
142
+
143
+ var input = inputs[inputs.length - 1]
144
+
145
+ var value = input.value
146
+
147
+ if (key) {
148
+ newmap[key] = value || ''
149
+ }
150
+ }
151
+
152
+ this.value = newmap
153
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
154
+ }
155
+
156
+ /* map아이템들을 template(dom-repeat)용 배열로 변환하는 함수 */
157
+ _toArray(map: PartitionKeys) {
158
+ var array: ArrayedPartitionKeys[] = []
159
+
160
+ for (var key in map) {
161
+ array.push({
162
+ key: key,
163
+ value: map[key]
164
+ })
165
+ }
166
+
167
+ return array
168
+ }
169
+
170
+ _add() {
171
+ this._build(true)
172
+
173
+ const inputs = this.renderRoot.querySelectorAll(
174
+ '[data-record-new] input:not([style*="display: none"])'
175
+ ) as NodeListOf<HTMLInputElement & { value: any }>
176
+
177
+ for (var i = 0; i < inputs.length; i++) {
178
+ let input = inputs[i]
179
+
180
+ if (input.type == 'checkbox') input.checked = false
181
+ else input.value = ''
182
+ }
183
+
184
+ inputs[0].focus()
185
+ }
186
+
187
+ _delete(e: MouseEvent) {
188
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
189
+
190
+ ;(record!.querySelector('[data-key]') as HTMLInputElement)!.value = ''
191
+
192
+ this._build()
193
+ }
194
+
195
+ @queryAll('[data-record]') records!: NodeListOf<HTMLElement>
196
+
197
+ _up(e: MouseEvent) {
198
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
199
+ const array = Array.from(this.records)
200
+ const index = array.indexOf(record) - 1
201
+
202
+ if (index < 0) {
203
+ return
204
+ }
205
+
206
+ const deleted = array.splice(index, 1)
207
+ array.splice(index + 1, 0, ...deleted)
208
+
209
+ this.value = array.reduce((sum, record) => {
210
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
211
+ const value = (record.querySelector('[data-value]') as HTMLInputElement).value
212
+
213
+ sum[key] = value
214
+ return sum
215
+ }, {} as { [key: string]: string })
216
+
217
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
218
+ }
219
+
220
+ _down(e: MouseEvent) {
221
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
222
+ const array = Array.from(this.records)
223
+ const index = array.indexOf(record)
224
+
225
+ if (index > array.length) {
226
+ return
227
+ }
228
+
229
+ array.splice(index, 1)
230
+ array.splice(index + 1, 0, record)
231
+
232
+ this.value = array.reduce((sum, record) => {
233
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
234
+ const value = (record.querySelector('[data-value]') as HTMLInputElement).value
235
+
236
+ sum[key] = value
237
+ return sum
238
+ }, {} as { [key: string]: string })
239
+
240
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
241
+ }
242
+ }