@operato/input 1.0.0-beta.19 → 1.0.0-beta.21

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 (37) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/src/ox-input-key-values.d.ts +41 -0
  3. package/dist/src/ox-input-key-values.js +232 -0
  4. package/dist/src/ox-input-key-values.js.map +1 -0
  5. package/dist/src/ox-input-value-map.d.ts +2 -2
  6. package/dist/src/ox-input-value-map.js +1 -1
  7. package/dist/src/ox-input-value-map.js.map +1 -1
  8. package/dist/src/ox-input-value-ranges.d.ts +2 -2
  9. package/dist/src/ox-input-value-ranges.js.map +1 -1
  10. package/dist/stories/ox-input-key-values.stories.d.ts +29 -0
  11. package/dist/stories/ox-input-key-values.stories.js +49 -0
  12. package/dist/stories/ox-input-key-values.stories.js.map +1 -0
  13. package/dist/stories/ox-input-partition-keys.stories.d.ts +0 -2
  14. package/dist/stories/ox-input-partition-keys.stories.js +0 -18
  15. package/dist/stories/ox-input-partition-keys.stories.js.map +1 -1
  16. package/dist/stories/ox-input-value-map.stories copy.d.ts +35 -0
  17. package/dist/stories/ox-input-value-map.stories copy.js +37 -0
  18. package/dist/stories/ox-input-value-map.stories copy.js.map +1 -0
  19. package/dist/stories/ox-input-value-map.stories.d.ts +35 -0
  20. package/dist/stories/ox-input-value-map.stories.js +37 -0
  21. package/dist/stories/ox-input-value-map.stories.js.map +1 -0
  22. package/dist/stories/ox-input-value-range.stories.d.ts +35 -0
  23. package/dist/stories/ox-input-value-range.stories.js +37 -0
  24. package/dist/stories/ox-input-value-range.stories.js.map +1 -0
  25. package/dist/stories/ox-input-value-ranges.stories.d.ts +35 -0
  26. package/dist/stories/ox-input-value-ranges.stories.js +37 -0
  27. package/dist/stories/ox-input-value-ranges.stories.js.map +1 -0
  28. package/dist/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +8 -7
  30. package/src/ox-input-key-values.ts +269 -0
  31. package/src/ox-input-value-map.ts +2 -2
  32. package/src/ox-input-value-ranges.ts +2 -2
  33. package/stories/ox-input-code.stories.ts_ +0 -20
  34. package/stories/ox-input-key-values.stories.ts +64 -0
  35. package/stories/ox-input-partition-keys.stories.ts +0 -20
  36. package/stories/ox-input-value-map.stories.ts +58 -0
  37. package/stories/ox-input-value-ranges.stories.ts +58 -0
@@ -0,0 +1,269 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import '@material/mwc-icon'
6
+
7
+ import { css, html } from 'lit'
8
+ import { customElement, property, queryAll } from 'lit/decorators.js'
9
+
10
+ import { OxFormField } from './ox-form-field'
11
+
12
+ type KeyValues = { [key: string]: any }
13
+ type ArrayedKeyValues = { key: string; value: any }
14
+
15
+ /**
16
+ input component for key-value map
17
+
18
+ Example:
19
+
20
+ <ox-input-key-values
21
+ value=${map}
22
+ </ox-input-key-values>
23
+ */
24
+ @customElement('ox-input-key-values')
25
+ export class OxInputKeyValues extends OxFormField {
26
+ static styles = css`
27
+ :host {
28
+ display: flex;
29
+ flex-direction: column;
30
+ overflow: hidden;
31
+ margin-bottom: var(--margin-wide);
32
+ }
33
+
34
+ div {
35
+ display: flex;
36
+ flex-flow: row nowrap;
37
+ gap: var(--margin-default);
38
+ margin-bottom: var(--margin-narrow);
39
+ }
40
+
41
+ button {
42
+ border: var(--button-border);
43
+ border-radius: var(--border-radius);
44
+ background-color: var(--button-background-color);
45
+ padding: var(--padding-narrow) var(--padding-default);
46
+ line-height: 0.8;
47
+ color: var(--button-color);
48
+ cursor: pointer;
49
+ }
50
+ button + button {
51
+ margin-left: -5px;
52
+ }
53
+ button mwc-icon {
54
+ font-size: var(--fontsize-default);
55
+ }
56
+ button:focus,
57
+ button:hover,
58
+ button:active {
59
+ border: var(--button-activ-border);
60
+ background-color: var(--button-background-focus-color);
61
+ color: var(--theme-white-color);
62
+ }
63
+
64
+ input {
65
+ flex: 1;
66
+ border: 0;
67
+ border-bottom: var(--border-dark-color);
68
+ padding: var(--input-padding);
69
+ font: var(--input-font);
70
+ color: var(--primary-text-color);
71
+ }
72
+ input:focus {
73
+ outline: none;
74
+ border-bottom: 1px solid var(--primary-color);
75
+ }
76
+ button.hidden {
77
+ opacity: 0;
78
+ cursor: default;
79
+ }
80
+ `
81
+
82
+ @property({ type: Object }) value: KeyValues = {}
83
+ @property({ type: Object }) options: { display: string; value: string }[] = []
84
+
85
+ private _changingNow: boolean = false
86
+
87
+ firstUpdated() {
88
+ this.renderRoot.addEventListener('change', this._onChange.bind(this))
89
+ }
90
+
91
+ render() {
92
+ const value = !this.value || typeof this.value !== 'object' ? {} : this.value
93
+
94
+ return html`
95
+ ${this._toArray(value).map(
96
+ item => html`
97
+ <div data-record>
98
+ <input type="text" data-key placeholder="key" .value=${item.key} />
99
+ <input type="text" data-value placeholder="value" .value=${item.value} list="value-template" />
100
+ <button class="record-action" @click=${(e: MouseEvent) => this._delete(e)} tabindex="-1">
101
+ <mwc-icon>remove</mwc-icon>
102
+ </button>
103
+ <button class="record-action" @click=${(e: MouseEvent) => this._up(e)} tabindex="-1">
104
+ <mwc-icon>arrow_upward</mwc-icon>
105
+ </button>
106
+ <button class="record-action" @click=${(e: MouseEvent) => this._down(e)} tabindex="-1">
107
+ <mwc-icon>arrow_downward</mwc-icon>
108
+ </button>
109
+ </div>
110
+ `
111
+ )}
112
+
113
+ <div data-record-new>
114
+ <input type="text" data-key placeholder="key" value="" />
115
+ <input type="text" data-value placeholder="value" value="" list="value-template" />
116
+ <button class="record-action" @click=${(e: MouseEvent) => this._add()} tabindex="-1">
117
+ <mwc-icon>add</mwc-icon>
118
+ </button>
119
+ <button class="hidden"><mwc-icon>add</mwc-icon></button>
120
+ <button class="hidden"><mwc-icon>add</mwc-icon></button>
121
+ </div>
122
+
123
+ <datalist id="value-template">
124
+ ${this.options.map(({ display, value }) => html` <option value="${value}">${display}</option> `)}
125
+ </datalist>
126
+ `
127
+ }
128
+
129
+ _onChange(e: Event) {
130
+ if (this._changingNow) {
131
+ return
132
+ }
133
+
134
+ this._changingNow = true
135
+
136
+ const input = e.target as HTMLInputElement
137
+
138
+ const record = (e.target as Element).closest('[data-record],[data-record-new]') as HTMLElement
139
+
140
+ if (record.hasAttribute('data-record')) {
141
+ this._build()
142
+ } else if (record.hasAttribute('data-record-new') && input.hasAttribute('data-value')) {
143
+ this._add()
144
+ }
145
+
146
+ this._changingNow = false
147
+ }
148
+
149
+ _build(includeNewRecord?: boolean) {
150
+ if (includeNewRecord) {
151
+ var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]') as NodeListOf<HTMLElement>
152
+ } else {
153
+ var records = this.renderRoot.querySelectorAll('[data-record]') as NodeListOf<HTMLElement>
154
+ }
155
+
156
+ var newmap: KeyValues = {}
157
+
158
+ for (var i = 0; i < records.length; i++) {
159
+ var record = records[i]
160
+
161
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
162
+ const inputs = record.querySelectorAll(
163
+ '[data-value]:not([style*="display: none"])'
164
+ ) as NodeListOf<HTMLInputElement>
165
+
166
+ if (!inputs || inputs.length == 0) {
167
+ continue
168
+ }
169
+
170
+ var input = inputs[inputs.length - 1]
171
+
172
+ var value = input.value
173
+
174
+ if (key) {
175
+ newmap[key] = value || ''
176
+ }
177
+ }
178
+
179
+ this.value = newmap
180
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
181
+ }
182
+
183
+ /* map아이템들을 template(dom-repeat)용 배열로 변환하는 함수 */
184
+ _toArray(map: KeyValues) {
185
+ var array: ArrayedKeyValues[] = []
186
+
187
+ for (var key in map) {
188
+ array.push({
189
+ key: key,
190
+ value: map[key]
191
+ })
192
+ }
193
+
194
+ return array
195
+ }
196
+
197
+ _add() {
198
+ this._build(true)
199
+
200
+ const inputs = this.renderRoot.querySelectorAll(
201
+ '[data-record-new] input:not([style*="display: none"])'
202
+ ) as NodeListOf<HTMLInputElement & { value: any }>
203
+
204
+ for (var i = 0; i < inputs.length; i++) {
205
+ let input = inputs[i]
206
+
207
+ if (input.type == 'checkbox') input.checked = false
208
+ else input.value = ''
209
+ }
210
+
211
+ inputs[0].focus()
212
+ }
213
+
214
+ _delete(e: MouseEvent) {
215
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
216
+
217
+ ;(record!.querySelector('[data-key]') as HTMLInputElement)!.value = ''
218
+
219
+ this._build()
220
+ }
221
+
222
+ @queryAll('[data-record]') records!: NodeListOf<HTMLElement>
223
+
224
+ _up(e: MouseEvent) {
225
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
226
+ const array = Array.from(this.records)
227
+ const index = array.indexOf(record) - 1
228
+
229
+ if (index < 0) {
230
+ return
231
+ }
232
+
233
+ const deleted = array.splice(index, 1)
234
+ array.splice(index + 1, 0, ...deleted)
235
+
236
+ this.value = array.reduce((sum, record) => {
237
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
238
+ const value = (record.querySelector('[data-value]') as HTMLInputElement).value
239
+
240
+ sum[key] = value
241
+ return sum
242
+ }, {} as { [key: string]: string })
243
+
244
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
245
+ }
246
+
247
+ _down(e: MouseEvent) {
248
+ const record = (e.target as Element).closest('[data-record]') as HTMLElement
249
+ const array = Array.from(this.records)
250
+ const index = array.indexOf(record)
251
+
252
+ if (index > array.length) {
253
+ return
254
+ }
255
+
256
+ array.splice(index, 1)
257
+ array.splice(index + 1, 0, record)
258
+
259
+ this.value = array.reduce((sum, record) => {
260
+ const key = (record.querySelector('[data-key]') as HTMLInputElement).value
261
+ const value = (record.querySelector('[data-value]') as HTMLInputElement).value
262
+
263
+ sum[key] = value
264
+ return sum
265
+ }, {} as { [key: string]: string })
266
+
267
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))
268
+ }
269
+ }
@@ -80,8 +80,8 @@ export class OxInputValueMap extends OxFormField {
80
80
  `
81
81
 
82
82
  @property({ type: Object }) value: ValueMap = {}
83
- @property({ type: String }) valuetype: 'string' | 'boolean' | 'color' | string = 'string'
84
- @property({ type: String }) keytype: 'string' | 'boolean' | 'color' | string = 'string'
83
+ @property({ type: String }) valuetype: 'string' | 'boolean' | 'color' | 'number' | 'date' | string = 'string'
84
+ @property({ type: String }) keytype: 'string' | 'number' = 'number'
85
85
 
86
86
  private _changingNow: boolean = false
87
87
 
@@ -92,8 +92,8 @@ export class OxInputValueRange extends OxFormField {
92
92
  `
93
93
 
94
94
  @property({ type: Object }) value: ValueRange = {}
95
- @property({ type: String }) valuetype: 'string' | 'boolean' | 'color' | string = 'string'
96
- @property({ type: String }) rangetype: 'string' | 'boolean' | 'color' | string = 'number'
95
+ @property({ type: String }) valuetype: 'string' | 'boolean' | 'color' | 'number' | 'date' | string = 'string'
96
+ @property({ type: String }) rangetype: 'string' | 'number' = 'number'
97
97
 
98
98
  private _changingNow: boolean = false
99
99
 
@@ -49,23 +49,3 @@ Regular.args = {
49
49
  C: 'C'
50
50
  }
51
51
  }
52
-
53
- export const BooleanValues = Template.bind({})
54
- BooleanValues.args = {
55
- name: 'code',
56
- value: {
57
- A: true,
58
- B: false,
59
- C: true
60
- }
61
- }
62
-
63
- export const ColorValues = Template.bind({})
64
- ColorValues.args = {
65
- name: 'code',
66
- value: {
67
- A: 'red',
68
- B: 'yellow',
69
- C: 'blue'
70
- }
71
- }
@@ -0,0 +1,64 @@
1
+ import '../src/ox-input-key-values.js'
2
+
3
+ import { html, TemplateResult } from 'lit'
4
+
5
+ export default {
6
+ title: 'ox-input-key-values',
7
+ component: 'ox-input-key-values',
8
+ argTypes: {
9
+ name: { control: 'text' },
10
+ value: { control: 'object' },
11
+ options: { control: 'object' }
12
+ }
13
+ }
14
+
15
+ interface Story<T> {
16
+ (args: T): TemplateResult
17
+ args?: Partial<T>
18
+ argTypes?: Record<string, unknown>
19
+ }
20
+
21
+ interface ArgTypes {
22
+ name?: string
23
+ value?: object
24
+ options?: object
25
+ }
26
+
27
+ const Template: Story<ArgTypes> = ({ name = 'key-values', value = {}, options = [] }: ArgTypes) => html`
28
+ <link href="/themes/app-theme.css" rel="stylesheet" />
29
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
30
+ <style>
31
+ body {
32
+ }
33
+ </style>
34
+
35
+ <ox-input-key-values
36
+ @change=${(e: Event) => {
37
+ console.log((e.target as HTMLInputElement).value)
38
+ }}
39
+ name=${name}
40
+ .value=${value}
41
+ .options=${options}
42
+ >
43
+ </ox-input-key-values>
44
+ `
45
+
46
+ export const Regular = Template.bind({})
47
+ Regular.args = {
48
+ name: 'key-values',
49
+ value: {
50
+ A: 'A',
51
+ B: 'B',
52
+ C: 'C'
53
+ },
54
+ options: [
55
+ {
56
+ display: '초기값',
57
+ value: 'ABC'
58
+ },
59
+ {
60
+ display: '후기값',
61
+ value: 'XYZ'
62
+ }
63
+ ]
64
+ }
@@ -49,23 +49,3 @@ Regular.args = {
49
49
  C: 'C'
50
50
  }
51
51
  }
52
-
53
- export const BooleanValues = Template.bind({})
54
- BooleanValues.args = {
55
- name: 'partition-keys',
56
- value: {
57
- A: true,
58
- B: false,
59
- C: true
60
- }
61
- }
62
-
63
- export const ColorValues = Template.bind({})
64
- ColorValues.args = {
65
- name: 'partition-keys',
66
- value: {
67
- A: 'red',
68
- B: 'yellow',
69
- C: 'blue'
70
- }
71
- }
@@ -0,0 +1,58 @@
1
+ import '../src/ox-input-value-map.js'
2
+
3
+ import { html, TemplateResult } from 'lit'
4
+
5
+ export default {
6
+ title: 'ox-input-value-map',
7
+ component: 'ox-input-value-map',
8
+ argTypes: {
9
+ name: { control: 'text' },
10
+ value: { control: 'object' },
11
+ keytype: { control: 'select', options: ['string', 'number'] },
12
+ valuetype: { control: 'select', options: ['string', 'boolean', 'number', 'color', 'date'] }
13
+ }
14
+ }
15
+
16
+ interface Story<T> {
17
+ (args: T): TemplateResult
18
+ args?: Partial<T>
19
+ argTypes?: Record<string, unknown>
20
+ }
21
+
22
+ interface ArgTypes {
23
+ name?: string
24
+ value?: object
25
+ valuetype?: string
26
+ keytype?: string
27
+ }
28
+
29
+ const Template: Story<ArgTypes> = ({
30
+ name = 'values',
31
+ value = {},
32
+ keytype = 'string',
33
+ valuetype = 'string'
34
+ }: ArgTypes) => html`
35
+ <link href="/themes/app-theme.css" rel="stylesheet" />
36
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
37
+ <style>
38
+ body {
39
+ }
40
+ </style>
41
+
42
+ <ox-input-value-map
43
+ @change=${(e: Event) => {
44
+ console.log((e.target as HTMLInputElement).value)
45
+ }}
46
+ name=${name}
47
+ .value=${value}
48
+ keytype=${keytype}
49
+ valuetype=${valuetype}
50
+ >
51
+ </ox-input-value-map>
52
+ `
53
+
54
+ export const Regular = Template.bind({})
55
+ Regular.args = {
56
+ name: 'values',
57
+ value: {}
58
+ }
@@ -0,0 +1,58 @@
1
+ import '../src/ox-input-value-ranges.js'
2
+
3
+ import { html, TemplateResult } from 'lit'
4
+
5
+ export default {
6
+ title: 'ox-input-value-ranges',
7
+ component: 'ox-input-value-ranges',
8
+ argTypes: {
9
+ name: { control: 'text' },
10
+ value: { control: 'object' },
11
+ keytype: { control: 'select', options: ['string', 'number'] },
12
+ valuetype: { control: 'select', options: ['string', 'boolean', 'number', 'color', 'date'] }
13
+ }
14
+ }
15
+
16
+ interface Story<T> {
17
+ (args: T): TemplateResult
18
+ args?: Partial<T>
19
+ argTypes?: Record<string, unknown>
20
+ }
21
+
22
+ interface ArgTypes {
23
+ name?: string
24
+ value?: object
25
+ valuetype?: string
26
+ keytype?: string
27
+ }
28
+
29
+ const Template: Story<ArgTypes> = ({
30
+ name = 'values',
31
+ value = {},
32
+ keytype = 'string',
33
+ valuetype = 'string'
34
+ }: ArgTypes) => html`
35
+ <link href="/themes/app-theme.css" rel="stylesheet" />
36
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
37
+ <style>
38
+ body {
39
+ }
40
+ </style>
41
+
42
+ <ox-input-value-ranges
43
+ @change=${(e: Event) => {
44
+ console.log((e.target as HTMLInputElement).value)
45
+ }}
46
+ name=${name}
47
+ .value=${value}
48
+ keytype=${keytype}
49
+ valuetype=${valuetype}
50
+ >
51
+ </ox-input-value-ranges>
52
+ `
53
+
54
+ export const Regular = Template.bind({})
55
+ Regular.args = {
56
+ name: 'values',
57
+ value: {}
58
+ }