@operato/data-grist 0.3.13 → 0.3.17

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 (126) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/assets/images/no-image.png +0 -0
  3. package/custom-elements.json +2382 -1803
  4. package/demo/index.html +41 -62
  5. package/dist/src/configure/list-option-builder.js +0 -2
  6. package/dist/src/configure/list-option-builder.js.map +1 -1
  7. package/dist/src/configure/zero-config.d.ts +0 -1
  8. package/dist/src/configure/zero-config.js +0 -2
  9. package/dist/src/configure/zero-config.js.map +1 -1
  10. package/dist/src/data-card/data-card.d.ts +3 -6
  11. package/dist/src/data-card/data-card.js +3 -131
  12. package/dist/src/data-card/data-card.js.map +1 -1
  13. package/dist/src/data-card/record-card.d.ts +0 -3
  14. package/dist/src/data-card/record-card.js +22 -71
  15. package/dist/src/data-card/record-card.js.map +1 -1
  16. package/dist/src/data-grid/data-grid-body.d.ts +7 -1
  17. package/dist/src/data-grid/data-grid-body.js +26 -5
  18. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  19. package/dist/src/data-grid/data-grid-field.js +1 -1
  20. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  21. package/dist/src/data-grid/data-grid-header.d.ts +1 -0
  22. package/dist/src/data-grid/data-grid-header.js +9 -1
  23. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  24. package/dist/src/data-grid/data-grid.d.ts +8 -4
  25. package/dist/src/data-grid/data-grid.js +12 -132
  26. package/dist/src/data-grid/data-grid.js.map +1 -1
  27. package/dist/src/data-grist.d.ts +1 -0
  28. package/dist/src/data-grist.js +3 -0
  29. package/dist/src/data-grist.js.map +1 -1
  30. package/dist/src/data-list/data-list.d.ts +3 -6
  31. package/dist/src/data-list/data-list.js +3 -131
  32. package/dist/src/data-list/data-list.js.map +1 -1
  33. package/dist/src/data-list/record-partial.d.ts +0 -2
  34. package/dist/src/data-list/record-partial.js +7 -58
  35. package/dist/src/data-list/record-partial.js.map +1 -1
  36. package/dist/src/data-manipulator.d.ts +20 -0
  37. package/dist/src/data-manipulator.js +148 -0
  38. package/dist/src/data-manipulator.js.map +1 -0
  39. package/dist/src/editors/image-editor.d.ts +9 -0
  40. package/dist/src/editors/image-editor.js +53 -0
  41. package/dist/src/editors/image-editor.js.map +1 -0
  42. package/dist/src/editors/image-input.d.ts +7 -0
  43. package/dist/src/editors/image-input.js +31 -0
  44. package/dist/src/editors/image-input.js.map +1 -0
  45. package/dist/src/editors/index.d.ts +1 -0
  46. package/dist/src/editors/index.js +1 -0
  47. package/dist/src/editors/index.js.map +1 -1
  48. package/dist/src/editors/input-editors copy.d.ts +75 -0
  49. package/dist/src/editors/input-editors copy.js +373 -0
  50. package/dist/src/editors/input-editors copy.js.map +1 -0
  51. package/dist/src/editors/input-editors.d.ts +1 -8
  52. package/dist/src/editors/input-editors.js +3 -47
  53. package/dist/src/editors/input-editors.js.map +1 -1
  54. package/dist/src/editors/registry.d.ts +1 -1
  55. package/dist/src/editors/registry.js +2 -1
  56. package/dist/src/editors/registry.js.map +1 -1
  57. package/dist/src/handlers/record-view-handler.d.ts +1 -2
  58. package/dist/src/handlers/record-view-handler.js +5 -35
  59. package/dist/src/handlers/record-view-handler.js.map +1 -1
  60. package/dist/src/handlers/select-row-toggle.d.ts +1 -1
  61. package/dist/src/handlers/select-row-toggle.js.map +1 -1
  62. package/dist/src/record-view/event-handlers/record-view-body-click-handler.d.ts +7 -0
  63. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js +24 -0
  64. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js.map +1 -0
  65. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.d.ts +7 -0
  66. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js +22 -0
  67. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js.map +1 -0
  68. package/dist/src/record-view/index.d.ts +1 -0
  69. package/dist/src/record-view/index.js +1 -0
  70. package/dist/src/record-view/index.js.map +1 -1
  71. package/dist/src/record-view/record-creator copy.d.ts +13 -0
  72. package/dist/src/record-view/record-creator copy.js +90 -0
  73. package/dist/src/record-view/record-creator copy.js.map +1 -0
  74. package/dist/src/record-view/record-creator-backup.d.ts +13 -0
  75. package/dist/src/record-view/record-creator-backup.js +90 -0
  76. package/dist/src/record-view/record-creator-backup.js.map +1 -0
  77. package/dist/src/record-view/record-creator.d.ts +16 -0
  78. package/dist/src/record-view/record-creator.js +145 -0
  79. package/dist/src/record-view/record-creator.js.map +1 -0
  80. package/dist/src/record-view/record-view-body.d.ts +3 -4
  81. package/dist/src/record-view/record-view-body.js +15 -42
  82. package/dist/src/record-view/record-view-body.js.map +1 -1
  83. package/dist/src/record-view/record-view-handler.d.ts +9 -0
  84. package/dist/src/record-view/record-view-handler.js +57 -0
  85. package/dist/src/record-view/record-view-handler.js.map +1 -0
  86. package/dist/src/record-view/record-view.d.ts +5 -1
  87. package/dist/src/record-view/record-view.js +61 -36
  88. package/dist/src/record-view/record-view.js.map +1 -1
  89. package/dist/src/renderers/image-renderer.js +12 -4
  90. package/dist/src/renderers/image-renderer.js.map +1 -1
  91. package/dist/src/sorters/sorters-control.d.ts +12 -0
  92. package/dist/src/sorters/sorters-control.js +106 -0
  93. package/dist/src/sorters/sorters-control.js.map +1 -0
  94. package/dist/src/types.d.ts +2 -3
  95. package/dist/src/types.js.map +1 -1
  96. package/dist/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +10 -8
  98. package/src/configure/list-option-builder.ts +0 -2
  99. package/src/configure/zero-config.ts +0 -2
  100. package/src/data-card/data-card.ts +4 -158
  101. package/src/data-card/record-card.ts +30 -87
  102. package/src/data-grid/data-grid-body.ts +43 -6
  103. package/src/data-grid/data-grid-field.ts +1 -1
  104. package/src/data-grid/data-grid-header.ts +11 -1
  105. package/src/data-grid/data-grid.ts +25 -143
  106. package/src/data-grist.ts +4 -0
  107. package/src/data-list/data-list.ts +4 -158
  108. package/src/data-list/record-partial.ts +14 -73
  109. package/src/data-manipulator.ts +201 -0
  110. package/src/editors/image-input.ts +29 -0
  111. package/src/editors/index.ts +1 -0
  112. package/src/editors/input-editors.ts +5 -48
  113. package/src/editors/registry.ts +3 -4
  114. package/src/handlers/record-view-handler.ts +8 -44
  115. package/src/handlers/select-row-toggle.ts +1 -2
  116. package/src/record-view/event-handlers/record-view-body-click-handler.ts +30 -0
  117. package/src/record-view/event-handlers/record-view-body-keydown-handler.ts +26 -0
  118. package/src/record-view/index.ts +1 -0
  119. package/src/record-view/record-creator.ts +180 -0
  120. package/src/record-view/record-view-body.ts +16 -55
  121. package/src/record-view/record-view-handler.ts +86 -0
  122. package/src/record-view/record-view.ts +69 -42
  123. package/src/renderers/image-renderer.ts +14 -5
  124. package/src/sorters/sorters-control.ts +111 -0
  125. package/src/types.ts +10 -3
  126. package/yarn-error.log +16718 -0
@@ -8,6 +8,7 @@ import { css, html, LitElement, PropertyValues } from 'lit'
8
8
  import { customElement, property } from 'lit/decorators.js'
9
9
 
10
10
  import { ZERO_CONFIG, ZERO_DATA, ZERO_RECORD } from '../configure/zero-config'
11
+ import { RecordViewHandler } from '../record-view/record-view-handler'
11
12
  import { GristConfig, GristData, GristRecord } from '../types'
12
13
  import { recordCardClickHandler } from './event-handlers/record-card-click-handler'
13
14
  import { recordCardDblClickHandler } from './event-handlers/record-card-dblclick-handler'
@@ -67,7 +68,10 @@ export class RecordCard extends LitElement {
67
68
  border-top-right-radius: var(--data-card-record-card-border-radius);
68
69
  border-bottom: var(--data-card-thumbnail-border-bottom);
69
70
  overflow: hidden;
70
- align-self: center;
71
+
72
+ display: flex;
73
+ align-content: center;
74
+ justify-content: center;
71
75
  }
72
76
 
73
77
  [content] {
@@ -139,36 +143,6 @@ export class RecordCard extends LitElement {
139
143
  private clickHandler = recordCardClickHandler.bind(this) as EventListener
140
144
  private dblclickHandler = recordCardDblClickHandler.bind(this) as EventListener
141
145
 
142
- attributeChangedCallback(name: string, oldval: any, newval: any) {
143
- super.attributeChangedCallback(name, oldval, newval)
144
- }
145
-
146
- onFieldChange(e: Event) {
147
- /* record-view의 이벤트를 부모에게로 전달한다. */
148
- this.dispatchEvent(
149
- new CustomEvent('field-change', {
150
- bubbles: true,
151
- composed: true,
152
- detail: (e as any).detail
153
- })
154
- )
155
- }
156
-
157
- get recordView() {
158
- if (!this._recordView) {
159
- this._recordView = document.createElement('ox-record-view')
160
- this._recordView.addEventListener('field-change', (e: CustomEvent) => this.onFieldChange(e))
161
- }
162
-
163
- var columns = this.config.columns
164
-
165
- this._recordView.columns = columns
166
- this._recordView.record = this.record
167
- this._recordView.rowIndex = this.rowIndex
168
-
169
- return this._recordView
170
- }
171
-
172
146
  firstUpdated() {
173
147
  /*
174
148
  long-press
@@ -178,6 +152,8 @@ export class RecordCard extends LitElement {
178
152
  // this.renderRoot.addEventListener('long-press', recordPartialLongPressHandler.bind(this))
179
153
  this.renderRoot.addEventListener('click', this.clickHandler)
180
154
  this.renderRoot.addEventListener('dblclick', this.dblclickHandler)
155
+
156
+ this.addEventListener('show-record-view', () => this.popupRecordView())
181
157
  }
182
158
 
183
159
  updated(changes: PropertyValues<this>) {
@@ -187,18 +163,21 @@ export class RecordCard extends LitElement {
187
163
  }
188
164
 
189
165
  render() {
190
- var record = this.record
191
- var rowIndex = this.rowIndex
192
- var { columns, list } = this.config
193
- var { thumbnail, fields, details } = list || {}
166
+ const record = this.record
167
+ const rowIndex = this.rowIndex
168
+ const { columns, list } = this.config
169
+ const { thumbnail, fields, details } = list || {}
194
170
 
195
- var briefFields = fields.map(field => columns.find(column => column.name == field)).filter(column => column) || []
196
- var detailFields = details.map(field => columns.find(column => column.name == field)).filter(column => column) || []
171
+ const briefFields = fields.map(field => columns.find(column => column.name == field)).filter(column => column) || []
172
+ const detailFields =
173
+ details.map(field => columns.find(column => column.name == field)).filter(column => column) || []
197
174
 
198
- var thumbnailTemplate = thumbnail.call(this, record, rowIndex)
175
+ const thumbnailColumn = thumbnail ? columns.find(column => column.name == thumbnail) : undefined
176
+ const thumbRenderer = thumbnailColumn?.record.renderer
177
+ const thumbnailTemplate = thumbRenderer?.call(this, record[thumbnail!], thumbnailColumn!, record, rowIndex, this)
199
178
 
200
- var gutters = (columns || []).filter(column => column.type == 'gutter' && column.forList)
201
- var firstGutter = gutters[0]
179
+ const gutters = (columns || []).filter(column => column.type == 'gutter' && column.forList)
180
+ const firstGutter = gutters[0]
202
181
 
203
182
  if (this.hasAttribute('dirty')) {
204
183
  var dirtyIcon
@@ -301,53 +280,17 @@ export class RecordCard extends LitElement {
301
280
  title = column?.record.renderer(title, column, this.record, this.rowIndex, this /* cautious */)
302
281
  }
303
282
 
304
- document.dispatchEvent(
305
- new CustomEvent('open-popup', {
306
- detail: {
307
- template: this.recordView,
308
- options: {
309
- backdrop: true,
310
- size: 'large',
311
- title
312
- },
313
- callback: (popup: any) => {
314
- this.recordView.addEventListener('reset', () => {
315
- this.dispatchEvent(
316
- new CustomEvent('record-reset', {
317
- bubbles: true,
318
- composed: true,
319
- detail: {
320
- record: this.record,
321
- row: this.rowIndex
322
- }
323
- })
324
- )
325
- })
326
-
327
- this.recordView.addEventListener('cancel', () => {
328
- this.dispatchEvent(
329
- new CustomEvent('record-reset', {
330
- bubbles: true,
331
- composed: true,
332
- detail: {
333
- record: this.record,
334
- row: this.rowIndex
335
- }
336
- })
337
- )
338
- popup.close()
339
- })
340
-
341
- this.recordView.addEventListener('ok', () => {
342
- popup.close()
343
- })
344
-
345
- popup.onclosed = () => {
346
- delete this._recordView
347
- }
348
- }
349
- }
350
- })
283
+ this._recordView = RecordViewHandler(
284
+ this.config.columns,
285
+ this.record,
286
+ this.rowIndex,
287
+ this,
288
+ {
289
+ title
290
+ },
291
+ () => {
292
+ delete this._recordView
293
+ }
351
294
  )
352
295
  }
353
296
  }
@@ -1,16 +1,17 @@
1
1
  import './data-grid-field'
2
2
 
3
- import { ColumnConfig, GristConfig, GristData } from '../types'
4
- import { LitElement, PropertyValues, html } from 'lit'
5
- import { ZERO_CONFIG, ZERO_DATA } from '../configure/zero-config'
3
+ import { html, LitElement, PropertyValues } from 'lit'
6
4
  import { customElement, property } from 'lit/decorators.js'
5
+ import debounce from 'lodash-es/debounce'
7
6
 
7
+ import { ZERO_CONFIG, ZERO_DATA } from '../configure/zero-config'
8
+ import { RecordViewHandler } from '../record-view/record-view-handler'
9
+ import { ColumnConfig, GristConfig, GristData, GristRecord } from '../types'
10
+ import { supportsPassive } from '../utils'
11
+ import { dataGridBodyStyle } from './data-grid-body-style'
8
12
  import { dataGridBodyClickHandler } from './event-handlers/data-grid-body-click-handler'
9
13
  import { dataGridBodyDblclickHandler } from './event-handlers/data-grid-body-dblclick-handler'
10
14
  import { dataGridBodyKeydownHandler } from './event-handlers/data-grid-body-keydown-handler'
11
- import { dataGridBodyStyle } from './data-grid-body-style'
12
- import debounce from 'lodash-es/debounce'
13
- import { supportsPassive } from '../utils'
14
15
 
15
16
  const THRESHOLD = 300
16
17
  const DATA_PADDING = 3
@@ -58,6 +59,8 @@ export class DataGridBody extends LitElement {
58
59
  @property({ type: Number }) to = -1
59
60
 
60
61
  private _focusedListener?: (e: KeyboardEvent) => void
62
+ private _recordView?: any
63
+ private _recordViewRow?: number
61
64
 
62
65
  resetEdit() {
63
66
  this.editTarget = null
@@ -171,6 +174,10 @@ export class DataGridBody extends LitElement {
171
174
  '--focused-background-image',
172
175
  `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><rect fill='${primaryColor}' x='0' y='0' width='100%' height='100%' style='opacity:.3'/></svg>")`
173
176
  )
177
+
178
+ this.addEventListener('show-record-view', (e: Event) =>
179
+ this.popupRecordView((e as CustomEvent).detail as { row: number; record: GristRecord })
180
+ )
174
181
  }
175
182
 
176
183
  _onWheelEvent(e: WheelEvent) {
@@ -226,6 +233,10 @@ export class DataGridBody extends LitElement {
226
233
  this.scrollLeft = left
227
234
  }
228
235
  }
236
+
237
+ if (this._recordView) {
238
+ this._recordView.record = this.data.records[this._recordViewRow!]
239
+ }
229
240
  }
230
241
 
231
242
  focus() {
@@ -238,4 +249,30 @@ export class DataGridBody extends LitElement {
238
249
  this.focused = { row: row == -1 ? 0 : row, column: 0 }
239
250
  }
240
251
  }
252
+
253
+ popupRecordView({ record, row }: { row: number; record: GristRecord }) {
254
+ var titleField = this.config.list.fields[0] || 'name'
255
+ var title = record[titleField]
256
+
257
+ /* field가 오브젝트형인 경우에는 렌더러를 타이틀로 사용한다. */
258
+ if (typeof title == 'object') {
259
+ var column = this.config.columns.find(column => column.name == titleField)
260
+ title = column?.record.renderer(title, column, record, row, this /* cautious */)
261
+ }
262
+
263
+ this._recordViewRow = row
264
+ this._recordView = RecordViewHandler(
265
+ this.config.columns,
266
+ record,
267
+ row,
268
+ this,
269
+ {
270
+ title
271
+ },
272
+ () => {
273
+ delete this._recordView
274
+ delete this._recordViewRow
275
+ }
276
+ )
277
+ }
241
278
  }
@@ -118,7 +118,7 @@ export class DataGridField extends LitElement {
118
118
  if (changes.has('editing')) {
119
119
  if (this.isEditing) {
120
120
  this._onKeydownInEditingMode = ((e: KeyboardEvent) => {
121
- if (e.keyCode == 27 /* KEY_ESC */) {
121
+ if (e.key === 'Esc' || e.key === 'Escape') {
122
122
  /* 편집 취소 */
123
123
  this._editCancelled = true
124
124
  }
@@ -6,6 +6,7 @@ import { customElement, property, state } from 'lit/decorators.js'
6
6
  import throttle from 'lodash-es/throttle'
7
7
 
8
8
  import { OxPopup } from '@operato/popup'
9
+ import { closestElement } from '@operato/utils'
9
10
 
10
11
  import { ZERO_COLUMNS, ZERO_CONFIG, ZERO_DATA } from '../configure/zero-config'
11
12
  import { FilterStyles } from '../filters/filter-styles'
@@ -24,7 +25,7 @@ export class DataGridHeader extends LitElement {
24
25
  overflow: hidden;
25
26
  }
26
27
 
27
- :scope > div {
28
+ div[column] {
28
29
  display: flex;
29
30
 
30
31
  white-space: nowrap;
@@ -119,6 +120,15 @@ export class DataGridHeader extends LitElement {
119
120
  private _lastAccVal?: number
120
121
  private _throttledNotifier?: any
121
122
 
123
+ connectedCallback() {
124
+ super.connectedCallback()
125
+
126
+ const grid = closestElement('ox-grist', this)
127
+ grid?.addEventListener('sorters-change', (e: Event) => {
128
+ this._sorters = (e as CustomEvent).detail
129
+ })
130
+ }
131
+
122
132
  render() {
123
133
  var columns = this.columns || []
124
134
 
@@ -2,20 +2,21 @@ import './data-grid-header'
2
2
  import './data-grid-body'
3
3
  import './data-grid-footer'
4
4
 
5
- import { ColumnConfig, GristConfig, GristData, GristRecord, PaginationConfig } from '../types'
6
- import { LitElement, PropertyValues, css, html } from 'lit'
7
- import { ZERO_CONFIG, ZERO_DATA } from '../configure/zero-config'
5
+ import { css, html, LitElement, PropertyValues } from 'lit'
8
6
  import { customElement, property, query } from 'lit/decorators.js'
9
7
 
10
- import { DataGridHeader } from './data-grid-header'
11
8
  import { ScrollbarStyles } from '@operato/styles'
9
+
10
+ import { DataManipulator } from '../data-manipulator'
11
+ import { ColumnConfig, GristRecord, PaginationConfig } from '../types'
12
12
  import { supportsPassive } from '../utils'
13
+ import { DataGridHeader } from './data-grid-header'
13
14
 
14
15
  /**
15
16
  * DataGrid
16
17
  */
17
18
  @customElement('ox-grid')
18
- export class DataGrid extends LitElement {
19
+ export class DataGrid extends DataManipulator {
19
20
  static styles = [
20
21
  ScrollbarStyles,
21
22
  css`
@@ -40,8 +41,6 @@ export class DataGrid extends LitElement {
40
41
  `
41
42
  ]
42
43
 
43
- @property({ type: Object }) config: GristConfig = ZERO_CONFIG
44
- @property({ type: Object }) data: GristData = ZERO_DATA
45
44
  @property({ type: Object }) focused?: { row: number; column: number }
46
45
 
47
46
  @query('ox-grid-body', true) body!: LitElement
@@ -82,70 +81,11 @@ export class DataGrid extends LitElement {
82
81
  this.body.requestUpdate()
83
82
  })
84
83
 
85
- this.addEventListener('select-record-change', e => {
86
- var {
87
- records: selectedRecords,
88
- added = [],
89
- removed = []
90
- } = (e as CustomEvent).detail as {
91
- records: GristRecord[]
92
- added: GristRecord[]
93
- removed: GristRecord[]
94
- }
95
- var { records } = this.data
96
- var { selectable } = this.config.rows
97
-
98
- if (!records) {
99
- return
100
- }
101
-
102
- if (selectable && !selectable.multiple) {
103
- records.forEach(record => (record['__selected__'] = false))
104
- }
105
-
106
- if (selectedRecords) {
107
- records.forEach(record => (record['__selected__'] = false))
108
- selectedRecords.forEach(record => (record['__selected__'] = true))
109
- } else {
110
- removed.forEach(record => (record['__selected__'] = false))
111
- added.forEach(record => (record['__selected__'] = true))
112
- }
113
-
114
- this.header.requestUpdate()
115
- this.body.requestUpdate()
116
- })
117
-
118
- /* field change processing */
119
- this.addEventListener('field-change', e => {
120
- var { after, before, column, record, row } = (e as CustomEvent).detail
121
-
122
- /* compare changes */
123
- if (after === before) {
124
- return
125
- }
126
-
127
- var validation = column.validation
128
- if (validation && typeof (validation == 'function')) {
129
- if (!validation.call(this, after, before, record, column)) {
130
- return
131
- }
132
- }
133
-
134
- this.onRecordChanged({ [column.name]: after }, row, column)
135
- })
136
-
137
84
  this.addEventListener('focus-change', e => {
138
85
  this.focused = (e as CustomEvent).detail
139
86
  this.focus()
140
87
  this.requestUpdate()
141
88
  })
142
-
143
- /* record reset processing */
144
- this.addEventListener('record-reset', e => {
145
- var { record, row } = (e as CustomEvent).detail
146
-
147
- this.onRecordChanged(record['__origin__'], row, null)
148
- })
149
89
  }
150
90
 
151
91
  onWheelEvent(e: WheelEvent) {
@@ -155,89 +95,31 @@ export class DataGrid extends LitElement {
155
95
  supportsPassive || e.preventDefault()
156
96
  }
157
97
 
98
+ onSelectRecordChanged({
99
+ selectedRecords,
100
+ added,
101
+ removed
102
+ }: {
103
+ selectedRecords: GristRecord[]
104
+ added: GristRecord[]
105
+ removed: GristRecord[]
106
+ }): void {
107
+ super.onSelectRecordChanged({ selectedRecords, added, removed })
108
+
109
+ this.header.requestUpdate()
110
+ this.body.requestUpdate()
111
+ }
112
+
158
113
  onRecordChanged(
159
114
  recordData: GristRecord,
160
115
  row: number,
161
116
  column: ColumnConfig | null /* TODO column should be removed */
162
117
  ) {
163
- // TODO 오브젝트나 배열 타입인 경우 deepCompare 후에 변경 적용 여부를 결정한다.
164
-
165
- /* 빈 그리드로 시작한 경우, data 설정이 되어있지 않을 수 있다. */
166
- var records = this.data.records
167
-
168
- var beforeRecord: GristRecord = records[row]
169
- var afterRecord: GristRecord
170
- var wantToDelete = false
171
- var wantToAppend = false
172
-
173
- if (!recordData) {
174
- if (!beforeRecord) {
175
- /* recordData가 없고, beforeRecord도 없다면, 레코드 생성 중에 리셋된 경우이므로 아무것도 하지 않는다. */
176
- this.requestUpdate()
177
- return
178
- } else {
179
- /*
180
- * beforeRecord가 있는데, 빈데이타로 업데이트하고자 한다면,
181
- * 삭제하고자 하는 의도로 이해된다. (주의 필요)
182
- */
183
- if (beforeRecord['__dirty__'] == '+') {
184
- wantToDelete = true
185
- } else {
186
- afterRecord = {
187
- ...beforeRecord,
188
- __dirty__: '-'
189
- }
190
- }
191
- }
192
- } else {
193
- if (!beforeRecord) {
194
- /* 기존 레코드가 없는 경우에는 새로운 레코드가 생성된다 */
195
- afterRecord = {
196
- ...recordData,
197
- __dirty__: '+'
198
- }
199
-
200
- wantToAppend = true
201
- } else {
202
- let beforeDirty = beforeRecord.__dirty__
203
- if (beforeDirty == '+') {
204
- /* 기존에 새로 생성된 레코드가 있었으며 계속 수정중이다. */
205
- afterRecord = {
206
- ...beforeRecord,
207
- ...recordData,
208
- __dirty__: '+'
209
- }
210
- } else {
211
- /* 기존에 레코드가 있었으며 계속 수정중이다. */
212
- afterRecord = {
213
- ...beforeRecord,
214
- ...recordData,
215
- __dirty__: 'M'
216
- }
217
- }
218
- }
219
- }
220
-
221
- if (wantToAppend) {
222
- records.push(afterRecord!)
223
- } else if (wantToDelete) {
224
- records.splice(row, 1)
225
- } else {
226
- records.splice(row, 1, afterRecord!)
227
- }
118
+ /* record-viewer grid 외에서 변경되는 경우에도 header와 body를 refresh 하도록 한다. */
119
+ super.onRecordChanged(recordData, row, column)
228
120
 
229
- this.dispatchEvent(
230
- new CustomEvent('record-change', {
231
- bubbles: true,
232
- composed: true,
233
- detail: {
234
- before: beforeRecord,
235
- after: afterRecord!,
236
- column,
237
- row
238
- }
239
- })
240
- )
121
+ this.header.requestUpdate()
122
+ this.body.requestUpdate()
241
123
  }
242
124
 
243
125
  updated(changes: PropertyValues<this>) {
package/src/data-grist.ts CHANGED
@@ -275,6 +275,10 @@ export class DataGrist extends LitElement implements DataConsumer {
275
275
  }
276
276
  }
277
277
 
278
+ get compiledConfig(): GristConfig {
279
+ return this._config
280
+ }
281
+
278
282
  get sorters(): SortersConfig | undefined {
279
283
  return this._config?.sorters
280
284
  }
@@ -1,14 +1,14 @@
1
1
  import '@material/mwc-icon'
2
2
  import './record-partial'
3
3
 
4
- import { css, html, LitElement, PropertyValues } from 'lit'
4
+ import { css, html, PropertyValues } from 'lit'
5
5
  import { customElement, property } from 'lit/decorators.js'
6
6
 
7
- import { ZERO_CONFIG, ZERO_DATA } from '../configure/zero-config'
8
- import { ColumnConfig, GristConfig, GristData, GristRecord } from '../types'
7
+ import { DataManipulator } from '../data-manipulator'
8
+ import { GristRecord } from '../types'
9
9
 
10
10
  @customElement('ox-list')
11
- export class DataList extends LitElement {
11
+ export class DataList extends DataManipulator {
12
12
  static styles = [
13
13
  css`
14
14
  :host {
@@ -42,8 +42,6 @@ export class DataList extends LitElement {
42
42
  `
43
43
  ]
44
44
 
45
- @property({ type: Object }) config: GristConfig = ZERO_CONFIG
46
- @property({ type: Object }) data: GristData = ZERO_DATA
47
45
  @property({ type: Boolean }) isTop: boolean = false
48
46
  @property({ type: Array }) private _records: GristRecord[] = []
49
47
 
@@ -71,158 +69,6 @@ export class DataList extends LitElement {
71
69
 
72
70
  this.isTop = this.scrollTop == 0
73
71
  })
74
-
75
- this.addEventListener('select-record-change', e => {
76
- var {
77
- records: selectedRecords,
78
- added = [],
79
- removed = []
80
- } = (e as CustomEvent).detail as {
81
- records: GristRecord[]
82
- added: GristRecord[]
83
- removed: GristRecord[]
84
- }
85
- var { records } = this.data || {}
86
- var { selectable = false } = this.config.rows || {}
87
-
88
- if (!records || !selectable) {
89
- return
90
- } else if (selectable && !selectable.multiple) {
91
- records.forEach(record => (record['__selected__'] = false))
92
- }
93
-
94
- if (selectedRecords) {
95
- records.forEach(record => (record['__selected__'] = false))
96
- selectedRecords.forEach(record => (record['__selected__'] = true))
97
- } else {
98
- removed.forEach(record => (record['__selected__'] = false))
99
- added.forEach(record => (record['__selected__'] = true))
100
- }
101
-
102
- this.requestUpdate()
103
- })
104
-
105
- /* field change processing */
106
- this.addEventListener('field-change', e => {
107
- var { after, before, column, record, row } = (e as CustomEvent).detail as {
108
- after: any
109
- before: any
110
- column: ColumnConfig
111
- record: GristRecord
112
- row: number
113
- }
114
-
115
- /* compare changes */
116
- if (after === before) {
117
- return
118
- }
119
-
120
- var validation = column.validation
121
- if (validation && typeof validation == 'function') {
122
- if (!validation.call(this, after, before, record, column)) {
123
- return
124
- }
125
- }
126
-
127
- this.onRecordChanged({ [column.name]: after }, row, column)
128
- })
129
-
130
- /* record reset processing */
131
- this.addEventListener('record-reset', e => {
132
- var { record, row } = (e as CustomEvent).detail as {
133
- record: GristRecord
134
- row: number
135
- }
136
-
137
- this.onRecordChanged(record['__origin__'], row, null)
138
- })
139
- }
140
-
141
- onRecordChanged(
142
- recordData: GristRecord,
143
- row: number,
144
- column: ColumnConfig | null /* TODO column should be removed */
145
- ) {
146
- // TODO 오브젝트나 배열 타입인 경우 deepCompare 후에 변경 적용 여부를 결정한다.
147
-
148
- /* 빈 그리드로 시작한 경우, data 설정이 되어있지 않을 수 있다. */
149
- var records = this.data.records
150
-
151
- var beforeRecord = records[row]
152
- var afterRecord: GristRecord
153
- var wantToDelete = false
154
- var wantToAppend = false
155
-
156
- if (!recordData) {
157
- if (!beforeRecord) {
158
- /* recordData가 없고, beforeRecord도 없다면, 레코드 생성 중에 리셋된 경우이므로 아무것도 하지 않는다. */
159
- this.requestUpdate()
160
- return
161
- } else {
162
- /*
163
- * beforeRecord가 있는데, 빈데이타로 업데이트하고자 한다면,
164
- * 삭제하고자 하는 의도로 이해된다. (주의 필요)
165
- */
166
- if (beforeRecord['__dirty__'] == '+') {
167
- wantToDelete = true
168
- } else {
169
- afterRecord = {
170
- ...beforeRecord,
171
- __dirty__: '-'
172
- }
173
- }
174
- }
175
- } else {
176
- if (!beforeRecord) {
177
- /* 기존 레코드가 없는 경우에는 새로운 레코드가 생성된다 */
178
- afterRecord = {
179
- ...recordData,
180
- __dirty__: '+'
181
- }
182
-
183
- wantToAppend = true
184
- } else {
185
- let beforeDirty = beforeRecord['__dirty__']
186
- if (beforeDirty == '+') {
187
- /* 기존에 새로 생성된 레코드가 있었으며 계속 수정중이다. */
188
- afterRecord = {
189
- ...beforeRecord,
190
- ...recordData,
191
- __dirty__: '+'
192
- }
193
- } else {
194
- /* 기존에 레코드가 있었으며 계속 수정중이다. */
195
- afterRecord = {
196
- ...beforeRecord,
197
- ...recordData,
198
- __dirty__: 'M'
199
- }
200
- }
201
- }
202
- }
203
-
204
- if (wantToAppend) {
205
- records.push(afterRecord!)
206
- } else if (wantToDelete) {
207
- records.splice(row, 1)
208
- } else {
209
- records.splice(row, 1, afterRecord!)
210
- }
211
-
212
- this.dispatchEvent(
213
- new CustomEvent('record-change', {
214
- bubbles: true,
215
- composed: true,
216
- detail: {
217
- before: beforeRecord,
218
- after: afterRecord!,
219
- column,
220
- row
221
- }
222
- })
223
- )
224
-
225
- this.requestUpdate()
226
72
  }
227
73
 
228
74
  updated(changes: PropertyValues<this>) {