@operato/data-grist 2.0.0-alpha.34 → 2.0.0-alpha.35

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 (46) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/src/data-grid/data-grid-body.d.ts +2 -2
  3. package/dist/src/data-grid/data-grid-body.js +4 -4
  4. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  5. package/dist/src/data-grid/data-grid-field.d.ts +1 -1
  6. package/dist/src/data-grid/data-grid-field.js +2 -2
  7. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  8. package/dist/src/editors/ox-grist-editor-checkbox.d.ts +2 -1
  9. package/dist/src/editors/ox-grist-editor-checkbox.js +9 -2
  10. package/dist/src/editors/ox-grist-editor-checkbox.js.map +1 -1
  11. package/dist/src/editors/ox-grist-editor-datetime.d.ts +1 -1
  12. package/dist/src/editors/ox-grist-editor-datetime.js +1 -2
  13. package/dist/src/editors/ox-grist-editor-datetime.js.map +1 -1
  14. package/dist/src/editors/ox-grist-editor-file.d.ts +2 -1
  15. package/dist/src/editors/ox-grist-editor-file.js +8 -2
  16. package/dist/src/editors/ox-grist-editor-file.js.map +1 -1
  17. package/dist/src/editors/ox-grist-editor-image.d.ts +1 -1
  18. package/dist/src/editors/ox-grist-editor-image.js +8 -8
  19. package/dist/src/editors/ox-grist-editor-image.js.map +1 -1
  20. package/dist/src/editors/ox-grist-editor-number.d.ts +2 -1
  21. package/dist/src/editors/ox-grist-editor-number.js +9 -9
  22. package/dist/src/editors/ox-grist-editor-number.js.map +1 -1
  23. package/dist/src/editors/ox-grist-editor-text.d.ts +1 -0
  24. package/dist/src/editors/ox-grist-editor-text.js +3 -0
  25. package/dist/src/editors/ox-grist-editor-text.js.map +1 -1
  26. package/dist/src/editors/ox-grist-editor-textarea.d.ts +1 -0
  27. package/dist/src/editors/ox-grist-editor-textarea.js +3 -0
  28. package/dist/src/editors/ox-grist-editor-textarea.js.map +1 -1
  29. package/dist/src/editors/ox-grist-editor.d.ts +2 -2
  30. package/dist/src/editors/ox-grist-editor.js +13 -15
  31. package/dist/src/editors/ox-grist-editor.js.map +1 -1
  32. package/dist/stories/dynamic-editable.stories.js +79 -80
  33. package/dist/stories/dynamic-editable.stories.js.map +1 -1
  34. package/dist/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +5 -5
  36. package/src/data-grid/data-grid-body.ts +5 -5
  37. package/src/data-grid/data-grid-field.ts +1 -1
  38. package/src/editors/ox-grist-editor-checkbox.ts +12 -2
  39. package/src/editors/ox-grist-editor-datetime.ts +1 -2
  40. package/src/editors/ox-grist-editor-file.ts +12 -2
  41. package/src/editors/ox-grist-editor-image.ts +10 -7
  42. package/src/editors/ox-grist-editor-number.ts +10 -9
  43. package/src/editors/ox-grist-editor-text.ts +4 -0
  44. package/src/editors/ox-grist-editor-textarea.ts +4 -0
  45. package/src/editors/ox-grist-editor.ts +13 -13
  46. package/stories/dynamic-editable.stories.ts +86 -86
@@ -87,7 +87,7 @@ export class DataGridField extends LitElement {
87
87
  @property({ type: Number }) columnIndex = 0
88
88
  @property({ type: Boolean }) editing = false
89
89
  @property({ type: Object }) value = {}
90
- @property({ type: String }) valueWithEdit: string | null = null
90
+ @property({ type: String }) valueWith: string | null = null
91
91
  @property({ attribute: false }) emphasized: any = false
92
92
  @property({ type: String }) fixed?: string
93
93
  @property({ type: String }) type?: string
@@ -4,8 +4,18 @@ import { html } from 'lit'
4
4
 
5
5
  @customElement('ox-grist-editor-checkbox')
6
6
  export class OxGristEditorCheckbox extends OxGristEditor {
7
- formatFromEditor(e: Event) {
8
- return (e.target as HTMLInputElement).checked
7
+ _onchange(e: Event) {
8
+ e.stopPropagation()
9
+
10
+ const input = e.target as HTMLInputElement
11
+
12
+ this._dirtyValue = this.formatFromEditor(input.checked)
13
+ }
14
+
15
+ formatFromEditor(value: any) {
16
+ if (typeof value == 'boolean') {
17
+ return value
18
+ }
9
19
  }
10
20
 
11
21
  formatForEditor(value: any): any {
@@ -15,8 +15,7 @@ export class OxGristEditorDateTime extends OxGristEditor {
15
15
  return new Date(timestamp - tzoffset).toISOString().slice(0, -1)
16
16
  }
17
17
 
18
- formatFromEditor(e: Event) {
19
- var value = (e.target as HTMLInputElement).value
18
+ formatFromEditor(value: any) {
20
19
  var datetime = new Date(value)
21
20
 
22
21
  return datetime.getTime()
@@ -5,8 +5,18 @@ import { OxGristEditor } from './ox-grist-editor.js'
5
5
 
6
6
  @customElement('ox-grist-editor-file')
7
7
  export class OxGristEditorFile extends OxGristEditor {
8
- formatFromEditor(e: Event): any {
9
- return (e.target as HTMLInputElement).files
8
+ _onchange(e: Event) {
9
+ e.stopPropagation()
10
+
11
+ const input = e.target as HTMLInputElement
12
+
13
+ this._dirtyValue = this.formatFromEditor(input.files)
14
+
15
+ this._onfocusout()
16
+ }
17
+
18
+ formatFromEditor(value: any): any {
19
+ return value
10
20
  }
11
21
 
12
22
  get editorTemplate() {
@@ -12,17 +12,20 @@ export class OxGristEditorImage extends OxGristEditor {
12
12
 
13
13
  _onchange(e: Event) {
14
14
  e.stopPropagation()
15
- this._dirtyValue = this.formatFromEditor(e)
16
- this._onfocusout()
17
- }
18
15
 
19
- formatFromEditor(e: Event) {
20
- // value가 image file object인지, image url인지 확인
21
16
  const input = e.target as HTMLInputElement
17
+
18
+ // value가 image file object인지, image url인지 확인
22
19
  if (input.files?.[0]) {
23
- return input.files[0]
20
+ this._dirtyValue = this.formatFromEditor(input.files[0])
24
21
  } else {
25
- return input.value
22
+ this._dirtyValue = this.formatFromEditor(input.value)
26
23
  }
24
+
25
+ this._onfocusout()
26
+ }
27
+
28
+ formatFromEditor(value: any) {
29
+ return value
27
30
  }
28
31
  }
@@ -5,17 +5,18 @@ import { parseToNumberOrNull } from '@operato/utils'
5
5
 
6
6
  @customElement('ox-grist-editor-number')
7
7
  export class OxGristEditorNumber extends OxGristEditor {
8
- formatFromEditor(e: Event) {
9
- let value = (e.target as HTMLInputElement).value
8
+ get inlineEditable() {
9
+ return true
10
+ }
11
+
12
+ formatFromEditor(value: any) {
13
+ const parsed = parseToNumberOrNull(value) || null
10
14
 
11
- switch (this.column.type) {
12
- case 'float':
13
- return Number.parseFloat(value) || 0
14
- case 'integer':
15
- return Number.parseInt(value) || 0
16
- default:
17
- return Number(value)
15
+ if (parsed !== null && this.column.type == 'integer') {
16
+ return Math.floor(parsed)
18
17
  }
18
+
19
+ return parsed
19
20
  }
20
21
 
21
22
  get editorTemplate() {
@@ -4,6 +4,10 @@ import { html } from 'lit'
4
4
 
5
5
  @customElement('ox-grist-editor-text')
6
6
  export class OxGristEditorText extends OxGristEditor {
7
+ get inlineEditable() {
8
+ return true
9
+ }
10
+
7
11
  get editorTemplate() {
8
12
  return html` <input type="text" .value=${this.value} /> `
9
13
  }
@@ -6,6 +6,10 @@ import { html } from 'lit'
6
6
 
7
7
  @customElement('ox-grist-editor-textarea')
8
8
  export class OxGristEditorTextarea extends OxGristEditor {
9
+ get inlineEditable() {
10
+ return true
11
+ }
12
+
9
13
  get editorTemplate() {
10
14
  return html` <ox-input-textarea .value=${this.value}></ox-input-textarea> `
11
15
  }
@@ -5,7 +5,6 @@ import { ZERO_COLUMN, ZERO_RECORD } from '../configure/zero-config'
5
5
  import { DataGridField } from '../data-grid/data-grid-field'
6
6
  import { ColumnConfig, GristRecord } from '../types'
7
7
  import { getDefaultValue } from '@operato/time-calculator'
8
- import { parseToNumberOrNull } from '@operato/utils'
9
8
 
10
9
  const STYLE = css`
11
10
  :host {
@@ -92,8 +91,8 @@ export class OxGristEditor extends LitElement {
92
91
  return this.renderRoot.firstElementChild as HTMLElement
93
92
  }
94
93
 
95
- get directEditable() {
96
- return true
94
+ get inlineEditable() {
95
+ return false
97
96
  }
98
97
 
99
98
  async firstUpdated() {
@@ -122,22 +121,21 @@ export class OxGristEditor extends LitElement {
122
121
  currentValue = getDefaultValue(defaultValue, this.record)
123
122
  }
124
123
 
124
+ this.value = this._dirtyValue = this.formatForEditor(currentValue)
125
+
125
126
  // 입력을 위한 키를 누르면서 편집모드가 될때는 누른 키가 처음에 입력되도록, enter 같은 것을 눌러서 편집모드가 되면 현재 값으로 편집모드 전환
126
- const editorValue = this.field?.valueWithEdit ? this.field.valueWithEdit : this.formatForEditor(currentValue)
127
- const fieldType = this.field?.type || 'string'
128
- this.value = this._dirtyValue = ['number', 'float', 'integer', 'progress'].includes(fieldType)
129
- ? parseToNumberOrNull(editorValue)
130
- : editorValue
127
+ const valueWith = this.inlineEditable && this.field?.valueWith
128
+ this.value = this._dirtyValue = valueWith ? this.formatFromEditor(valueWith) : this.formatForEditor(currentValue)
131
129
 
132
130
  requestAnimationFrame(() => {
133
131
  this.focus()
134
- this.select()
132
+ !valueWith && this.select()
135
133
  })
136
134
  }
137
135
 
138
136
  select() {
139
137
  const editor = this.editor
140
- if ((editor as HTMLInputElement)?.select && !this.field?.valueWithEdit) {
138
+ if ((editor as HTMLInputElement)?.select) {
141
139
  return (editor as HTMLInputElement).select()
142
140
  }
143
141
  }
@@ -153,8 +151,8 @@ export class OxGristEditor extends LitElement {
153
151
  return value == null ? '' : value
154
152
  }
155
153
 
156
- formatFromEditor(e: Event): any {
157
- return (e.target as HTMLInputElement).value
154
+ formatFromEditor(value: any): any {
155
+ return value
158
156
  }
159
157
 
160
158
  _onfocusout() {
@@ -184,7 +182,9 @@ export class OxGristEditor extends LitElement {
184
182
  _onchange(e: Event): void {
185
183
  e.stopPropagation()
186
184
 
187
- this._dirtyValue = this.formatFromEditor(e)
185
+ const value = (e.target as any)?.value
186
+
187
+ this._dirtyValue = this.formatFromEditor(value)
188
188
  }
189
189
 
190
190
  _onkeydown(e: Event): void {}
@@ -102,7 +102,8 @@ function buildConfig({ headerFilter }: { headerFilter: boolean }) {
102
102
  editable: (value: any, column: any, record: any, rowIndex: any, field: any) => {
103
103
  return record?.name !== 'heartyoh-3'
104
104
  }
105
- }
105
+ },
106
+ width: 40
106
107
  },
107
108
  {
108
109
  type: 'number',
@@ -192,102 +193,101 @@ interface ArgTypes {
192
193
  headerFilter: boolean
193
194
  }
194
195
 
195
- const Template: Story<ArgTypes> = ({ headerFilter }: ArgTypes) => html` <link
196
- href="https://fonts.googleapis.com/css?family=Material+Icons&display=block"
197
- rel="stylesheet"
198
- />
199
- <link href="/themes/app-theme.css" rel="stylesheet" />
200
- <link href="/themes/oops-theme.css" rel="stylesheet" />
201
- <link href="/themes/grist-theme.css" rel="stylesheet" />
202
-
203
- <style>
204
- [slot='headroom'] {
205
- display: flex;
206
- flex-direction: row;
207
- align-items: center;
208
- padding: var(--padding-default) var(--padding-wide);
209
- background-color: var(--theme-white-color);
210
- box-shadow: var(--box-shadow);
211
-
212
- --mdc-icon-size: 24px;
213
- }
214
- #sorters mwc-icon,
215
- #modes mwc-icon {
216
- --mdc-icon-size: 18px;
217
- }
218
- #sorters {
219
- margin-left: auto;
220
- margin-right: var(--margin-default);
221
- padding-left: var(--padding-narrow);
222
- border-bottom: var(--border-dark-color);
223
- position: relative;
224
- color: var(--secondary-color);
225
- font-size: var(--fontsize-default);
226
- user-select: none;
227
- }
196
+ const Template: Story<ArgTypes> = ({ headerFilter }: ArgTypes) =>
197
+ html` <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
198
+ <link href="/themes/app-theme.css" rel="stylesheet" />
199
+ <link href="/themes/oops-theme.css" rel="stylesheet" />
200
+ <link href="/themes/grist-theme.css" rel="stylesheet" />
228
201
 
229
- #sorters > * {
230
- padding: var(--padding-narrow);
231
- vertical-align: middle;
232
- }
202
+ <style>
203
+ [slot='headroom'] {
204
+ display: flex;
205
+ flex-direction: row;
206
+ align-items: center;
207
+ padding: var(--padding-default) var(--padding-wide);
208
+ background-color: var(--theme-white-color);
209
+ box-shadow: var(--box-shadow);
233
210
 
234
- #filters {
235
- display: flex;
236
- justify-content: center;
237
- align-items: center;
238
- }
211
+ --mdc-icon-size: 24px;
212
+ }
213
+ #sorters mwc-icon,
214
+ #modes mwc-icon {
215
+ --mdc-icon-size: 18px;
216
+ }
217
+ #sorters {
218
+ margin-left: auto;
219
+ margin-right: var(--margin-default);
220
+ padding-left: var(--padding-narrow);
221
+ border-bottom: var(--border-dark-color);
222
+ position: relative;
223
+ color: var(--secondary-color);
224
+ font-size: var(--fontsize-default);
225
+ user-select: none;
226
+ }
239
227
 
240
- #filters * {
241
- margin-right: var(--margin-default);
242
- }
228
+ #sorters > * {
229
+ padding: var(--padding-narrow);
230
+ vertical-align: middle;
231
+ }
243
232
 
244
- @media only screen and (max-width: 460px) {
245
233
  #filters {
246
- flex-direction: column;
234
+ display: flex;
235
+ justify-content: center;
236
+ align-items: center;
247
237
  }
248
238
 
249
- #modes {
250
- display: none;
239
+ #filters * {
240
+ margin-right: var(--margin-default);
251
241
  }
252
- }
253
- </style>
254
242
 
255
- <ox-grist
256
- .config=${buildConfig({ headerFilter })}
257
- mode="GRID"
258
- .fetchHandler=${fetchHandler}
259
- @filters-change=${(e: Event) => console.log('filters', (e.target as any).filters)}
260
- @field-change="${(e: any) => {
261
- console.log(e.detail.record.name, e.detail.record.number)
262
- }}"
263
- >
264
- <div slot="headroom">
265
- <div id="filters">
266
- <ox-filters-form></ox-filters-form>
267
- </div>
243
+ @media only screen and (max-width: 460px) {
244
+ #filters {
245
+ flex-direction: column;
246
+ }
268
247
 
269
- <div id="sorters">
270
- Sort
271
- <mwc-icon
272
- @click=${(e: Event) => {
273
- const target = e.currentTarget as HTMLElement
274
- ;(target.closest('#sorters')!.querySelector('#sorter-control') as any).open({
275
- right: 0,
276
- top: target.offsetTop + target.offsetHeight
277
- })
278
- }}
279
- >expand_more</mwc-icon
280
- >
281
- <ox-popup id="sorter-control">
282
- <ox-sorters-control> </ox-sorters-control>
283
- </ox-popup>
284
- </div>
248
+ #modes {
249
+ display: none;
250
+ }
251
+ }
252
+ </style>
253
+
254
+ <ox-grist
255
+ .config=${buildConfig({ headerFilter })}
256
+ mode="GRID"
257
+ .fetchHandler=${fetchHandler}
258
+ @filters-change=${(e: Event) => console.log('filters', (e.target as any).filters)}
259
+ @field-change=${(e: any) => {
260
+ const { name, number, chk } = e.detail.record
261
+ console.log(name, number, chk)
262
+ }}
263
+ >
264
+ <div slot="headroom">
265
+ <div id="filters">
266
+ <ox-filters-form></ox-filters-form>
267
+ </div>
285
268
 
286
- <ox-record-creator id="add" light-popup>
287
- <button><mwc-icon>add</mwc-icon></button>
288
- </ox-record-creator>
289
- </div>
290
- </ox-grist>`
269
+ <div id="sorters">
270
+ Sort
271
+ <mwc-icon
272
+ @click=${(e: Event) => {
273
+ const target = e.currentTarget as HTMLElement
274
+ ;(target.closest('#sorters')!.querySelector('#sorter-control') as any).open({
275
+ right: 0,
276
+ top: target.offsetTop + target.offsetHeight
277
+ })
278
+ }}
279
+ >expand_more</mwc-icon
280
+ >
281
+ <ox-popup id="sorter-control">
282
+ <ox-sorters-control> </ox-sorters-control>
283
+ </ox-popup>
284
+ </div>
285
+
286
+ <ox-record-creator id="add" light-popup>
287
+ <button><mwc-icon>add</mwc-icon></button>
288
+ </ox-record-creator>
289
+ </div>
290
+ </ox-grist>`
291
291
 
292
292
  export const Regular = Template.bind({})
293
293
  Regular.args = {}