@operato/data-grist 1.13.2 → 2.0.0-alpha.2
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.
- package/CHANGELOG.md +14 -2
- package/dist/src/configure/column-builder.js +3 -2
- package/dist/src/configure/column-builder.js.map +1 -1
- package/dist/src/configure/zero-config.js +3 -1
- package/dist/src/configure/zero-config.js.map +1 -1
- package/dist/src/data-grid/data-grid-accum-field.d.ts +1 -0
- package/dist/src/data-grid/data-grid-accum-field.js +8 -0
- package/dist/src/data-grid/data-grid-accum-field.js.map +1 -1
- package/dist/src/data-grid/data-grid-body.js +24 -2
- package/dist/src/data-grid/data-grid-body.js.map +1 -1
- package/dist/src/data-grid/data-grid-field.d.ts +1 -0
- package/dist/src/data-grid/data-grid-field.js +5 -0
- package/dist/src/data-grid/data-grid-field.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.d.ts +7 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.js +25 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.js.map +1 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-dblclick-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-dblclick-handler.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler copy.d.ts +7 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler copy.js +19 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler copy.js.map +1 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler.js.map +1 -1
- package/dist/src/data-manipulator.d.ts +3 -1
- package/dist/src/data-manipulator.js +20 -7
- package/dist/src/data-manipulator.js.map +1 -1
- package/dist/src/editors/ox-grist-editor-tree.d.ts +6 -0
- package/dist/src/editors/ox-grist-editor-tree.js +27 -0
- package/dist/src/editors/ox-grist-editor-tree.js.map +1 -0
- package/dist/src/editors/ox-grist-editor.d.ts +1 -0
- package/dist/src/editors/ox-grist-editor.js +3 -0
- package/dist/src/editors/ox-grist-editor.js.map +1 -1
- package/dist/src/editors/ox-input-tree.d.ts +20 -0
- package/dist/src/editors/ox-input-tree.js +221 -0
- package/dist/src/editors/ox-input-tree.js.map +1 -0
- package/dist/src/editors/registry.js +3 -1
- package/dist/src/editors/registry.js.map +1 -1
- package/dist/src/handlers/contextmenu-tree-mutation.d.ts +3 -0
- package/dist/src/handlers/contextmenu-tree-mutation.js +82 -0
- package/dist/src/handlers/contextmenu-tree-mutation.js.map +1 -0
- package/dist/src/handlers/contextmenu-tree.d.ts +3 -0
- package/dist/src/handlers/contextmenu-tree.js +30 -0
- package/dist/src/handlers/contextmenu-tree.js.map +1 -0
- package/dist/src/handlers/move-up copy.d.ts +3 -0
- package/dist/src/handlers/move-up copy.js +26 -0
- package/dist/src/handlers/move-up copy.js.map +1 -0
- package/dist/src/handlers/registry.js +3 -1
- package/dist/src/handlers/registry.js.map +1 -1
- package/dist/src/renderers/ox-grist-renderer-tree.d.ts +1 -0
- package/dist/src/renderers/ox-grist-renderer-tree.js +5 -2
- package/dist/src/renderers/ox-grist-renderer-tree.js.map +1 -1
- package/dist/src/types.d.ts +2 -1
- package/dist/src/types.js.map +1 -1
- package/dist/stories/tree-column-with-checkbox.stories.js +8 -3
- package/dist/stories/tree-column-with-checkbox.stories.js.map +1 -1
- package/dist/stories/tree-column.stories.js +8 -3
- package/dist/stories/tree-column.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/configure/column-builder.ts +3 -2
- package/src/configure/zero-config.ts +3 -1
- package/src/data-grid/data-grid-accum-field.ts +7 -0
- package/src/data-grid/data-grid-body.ts +30 -2
- package/src/data-grid/data-grid-field.ts +6 -0
- package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +2 -2
- package/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.ts +32 -0
- package/src/data-grid/event-handlers/data-grid-body-dblclick-handler.ts +2 -2
- package/src/data-grid/event-handlers/data-grid-body-focus-change-handler.ts +2 -2
- package/src/data-manipulator.ts +25 -8
- package/src/editors/ox-grist-editor-tree.ts +27 -0
- package/src/editors/ox-grist-editor.ts +4 -0
- package/src/editors/ox-input-tree.ts +226 -0
- package/src/editors/registry.ts +3 -1
- package/src/handlers/contextmenu-tree-mutation.ts +98 -0
- package/src/handlers/registry.ts +3 -1
- package/src/renderers/ox-grist-renderer-tree.ts +6 -2
- package/src/types.ts +3 -1
- package/stories/tree-column-with-checkbox.stories.ts +8 -3
- package/stories/tree-column.stories.ts +8 -3
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@operato/data-grist",
|
3
|
-
"version": "
|
3
|
+
"version": "2.0.0-alpha.2",
|
4
4
|
"description": "User interface for grid (desktop) and list (mobile)",
|
5
5
|
"author": "heartyoh",
|
6
6
|
"main": "dist/index.js",
|
@@ -56,12 +56,12 @@
|
|
56
56
|
},
|
57
57
|
"dependencies": {
|
58
58
|
"@material/mwc-icon": "^0.27.0",
|
59
|
-
"@operato/headroom": "^
|
60
|
-
"@operato/input": "^
|
61
|
-
"@operato/popup": "^
|
62
|
-
"@operato/pull-to-refresh": "^
|
63
|
-
"@operato/styles": "^
|
64
|
-
"@operato/utils": "^
|
59
|
+
"@operato/headroom": "^2.0.0-alpha.0",
|
60
|
+
"@operato/input": "^2.0.0-alpha.2",
|
61
|
+
"@operato/popup": "^2.0.0-alpha.2",
|
62
|
+
"@operato/pull-to-refresh": "^2.0.0-alpha.0",
|
63
|
+
"@operato/styles": "^2.0.0-alpha.0",
|
64
|
+
"@operato/utils": "^2.0.0-alpha.0",
|
65
65
|
"i18next": "^21.5.4",
|
66
66
|
"json5": "^2.2.0",
|
67
67
|
"lit": "^2.5.0",
|
@@ -100,5 +100,5 @@
|
|
100
100
|
"prettier --write"
|
101
101
|
]
|
102
102
|
},
|
103
|
-
"gitHead": "
|
103
|
+
"gitHead": "b940cc5dd44c22458ec03189e6bc8dae7f04f32e"
|
104
104
|
}
|
@@ -100,12 +100,13 @@ export const buildColumn = (column: any): ColumnConfig => {
|
|
100
100
|
}
|
101
101
|
|
102
102
|
/* handler */
|
103
|
-
var { click, dblclick, focus } = handlers || {}
|
103
|
+
var { click, dblclick, focus, contextmenu } = handlers || {}
|
104
104
|
|
105
105
|
compiled.handlers = {
|
106
106
|
click: click && getGristEventHandler(click),
|
107
107
|
dblclick: dblclick && getGristEventHandler(dblclick),
|
108
|
-
focus: focus && getGristEventHandler(focus)
|
108
|
+
focus: focus && getGristEventHandler(focus),
|
109
|
+
contextmenu: contextmenu && getGristEventHandler(contextmenu)
|
109
110
|
}
|
110
111
|
|
111
112
|
return compiled
|
@@ -18,7 +18,9 @@ export const ZERO_FIELD_RENDERER: FieldRenderer = (value, column, record, rowInd
|
|
18
18
|
|
19
19
|
export const ZERO_EVENTHANDLERSET: GristEventHandlerSet = {
|
20
20
|
click: undefined,
|
21
|
-
dblclick: undefined
|
21
|
+
dblclick: undefined,
|
22
|
+
focus: undefined,
|
23
|
+
contextmenu: undefined
|
22
24
|
}
|
23
25
|
export const ZERO_COLUMNS: ColumnConfig[] = []
|
24
26
|
export const ZERO_GROUPS: GroupConfig[] = []
|
@@ -58,6 +58,7 @@ export class DataGridAccumField extends LitElement {
|
|
58
58
|
@property({ type: Boolean }) editing = false
|
59
59
|
@property({ type: Object }) value = {}
|
60
60
|
@property({ attribute: false }) emphasized: any = false
|
61
|
+
@property({ type: String }) fixed?: string
|
61
62
|
|
62
63
|
render(): TemplateResult {
|
63
64
|
if (!this.column || !this.column.accumulator) {
|
@@ -90,5 +91,11 @@ export class DataGridAccumField extends LitElement {
|
|
90
91
|
this.style.setProperty('--data-grid-field-text-align', align)
|
91
92
|
}
|
92
93
|
}
|
94
|
+
|
95
|
+
if (changes.has('fixed')) {
|
96
|
+
if (this.fixed) {
|
97
|
+
this.style.left = this.fixed + 'px'
|
98
|
+
}
|
99
|
+
}
|
93
100
|
}
|
94
101
|
}
|
@@ -18,6 +18,7 @@ import { DataGridField } from './data-grid-field'
|
|
18
18
|
import { dataGridBodyClickHandler } from './event-handlers/data-grid-body-click-handler'
|
19
19
|
import { dataGridBodyDblclickHandler } from './event-handlers/data-grid-body-dblclick-handler'
|
20
20
|
import { dataGridBodyFocusChangeHandler } from './event-handlers/data-grid-body-focus-change-handler'
|
21
|
+
import { dataGridBodyContextMenuHandler } from './event-handlers/data-grid-body-contextmenu-handler'
|
21
22
|
import { dataGridBodyKeydownHandler } from './event-handlers/data-grid-body-keydown-handler'
|
22
23
|
import { accumulate } from '../accumulator/accumulator'
|
23
24
|
|
@@ -75,7 +76,7 @@ export class DataGridBody extends LitElement {
|
|
75
76
|
[fixed] {
|
76
77
|
position: sticky;
|
77
78
|
background-color: var(--grid-record-background-color);
|
78
|
-
z-index:
|
79
|
+
z-index: 2; /* 고정된 열을 다른 열 위에 표시. */
|
79
80
|
}
|
80
81
|
|
81
82
|
:host([raised]) [fixed] {
|
@@ -88,6 +89,10 @@ export class DataGridBody extends LitElement {
|
|
88
89
|
bottom: 0;
|
89
90
|
z-index: 1;
|
90
91
|
}
|
92
|
+
|
93
|
+
ox-grid-accum-field[fixed] {
|
94
|
+
background-color: var(--grid-accum-record-background-color, #ccc);
|
95
|
+
}
|
91
96
|
`
|
92
97
|
]
|
93
98
|
|
@@ -208,6 +213,7 @@ export class DataGridBody extends LitElement {
|
|
208
213
|
.column=${column}
|
209
214
|
.record=${accumRecord!}
|
210
215
|
.value=${accumRecord[column.name]}
|
216
|
+
fixed=${ifDefined(this.fixedLefts[idxColumn])}
|
211
217
|
></ox-grid-accum-field>
|
212
218
|
`
|
213
219
|
)}
|
@@ -261,6 +267,27 @@ export class DataGridBody extends LitElement {
|
|
261
267
|
this.setSelectBlock(start, end)
|
262
268
|
})
|
263
269
|
|
270
|
+
this.renderRoot.addEventListener('contextmenu', (event: Event) => {
|
271
|
+
const e = event as MouseEvent
|
272
|
+
this.setSelectBlock()
|
273
|
+
|
274
|
+
this._draggable = false
|
275
|
+
|
276
|
+
var target = (e.target as Element).closest('ox-grid-field') as DataGridField
|
277
|
+
var { rowIndex, columnIndex } = target || {}
|
278
|
+
|
279
|
+
this.dispatchEvent(
|
280
|
+
new CustomEvent('focus-change', {
|
281
|
+
bubbles: true,
|
282
|
+
composed: true,
|
283
|
+
detail: {
|
284
|
+
row: rowIndex,
|
285
|
+
column: columnIndex
|
286
|
+
}
|
287
|
+
})
|
288
|
+
)
|
289
|
+
})
|
290
|
+
|
264
291
|
this.renderRoot.addEventListener('mousedown', (event: Event) => {
|
265
292
|
const e = event as MouseEvent
|
266
293
|
this.setSelectBlock()
|
@@ -285,7 +312,7 @@ export class DataGridBody extends LitElement {
|
|
285
312
|
})
|
286
313
|
)
|
287
314
|
|
288
|
-
if (!isNaN(rowIndex) && !isNaN(columnIndex)) {
|
315
|
+
if (columnIndex >= 0 && target.editableOnClick && !isNaN(rowIndex) && !isNaN(columnIndex)) {
|
289
316
|
this.startEditTarget(rowIndex, columnIndex)
|
290
317
|
}
|
291
318
|
})
|
@@ -318,6 +345,7 @@ export class DataGridBody extends LitElement {
|
|
318
345
|
|
319
346
|
this.renderRoot.addEventListener('click', dataGridBodyClickHandler.bind(this))
|
320
347
|
this.renderRoot.addEventListener('dblclick', dataGridBodyDblclickHandler.bind(this))
|
348
|
+
this.renderRoot.addEventListener('contextmenu', dataGridBodyContextMenuHandler.bind(this))
|
321
349
|
|
322
350
|
this.addEventListener('focus-change', dataGridBodyFocusChangeHandler.bind(this))
|
323
351
|
|
@@ -173,4 +173,10 @@ export class DataGridField extends LitElement {
|
|
173
173
|
this.removeAttribute('emphasized-row')
|
174
174
|
}
|
175
175
|
}
|
176
|
+
|
177
|
+
get editableOnClick() {
|
178
|
+
const renderer = this.renderRoot.firstElementChild as HTMLElement
|
179
|
+
//@ts-ignore
|
180
|
+
return renderer && 'editableOnClick' in renderer ? renderer.editableOnClick : true
|
181
|
+
}
|
176
182
|
}
|
@@ -56,10 +56,10 @@ export function dataGridBodyClickHandler(this: DataGridBody, e: Event): void {
|
|
56
56
|
/* do column click handler */
|
57
57
|
if (column) {
|
58
58
|
var { click } = column.handlers
|
59
|
-
click && click(this.columns, this.data, column, record, rowIndex, target)
|
59
|
+
click && click(this.columns, this.data, column, record, rowIndex, target, e)
|
60
60
|
}
|
61
61
|
|
62
62
|
/* do rows click handler */
|
63
63
|
var { click: rowsClick } = this.config.rows.handlers
|
64
|
-
rowsClick && rowsClick(this.columns, this.data, column, record, rowIndex, target)
|
64
|
+
rowsClick && rowsClick(this.columns, this.data, column, record, rowIndex, target, e)
|
65
65
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { DataGridBody } from '../data-grid-body'
|
2
|
+
import { DataGridField } from '../data-grid-field'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* ox-grid-body 의 focus-change handler
|
6
|
+
*
|
7
|
+
* - handler의 this 는 ox-grid-body임.
|
8
|
+
*/
|
9
|
+
export async function dataGridBodyContextMenuHandler(this: DataGridBody, e: Event): Promise<void> {
|
10
|
+
e.stopPropagation()
|
11
|
+
|
12
|
+
if (this.editTarget) {
|
13
|
+
/* editTarget이 새로 설정되지 않았다면, 이후 기능이 실행된다. */
|
14
|
+
return
|
15
|
+
}
|
16
|
+
|
17
|
+
/* target should be 'ox-grid-field' */
|
18
|
+
var target = (e.target as Element).closest('ox-grid-field') as DataGridField
|
19
|
+
var { column, record, rowIndex, columnIndex } = target || {}
|
20
|
+
|
21
|
+
var { column, record } = target || {}
|
22
|
+
|
23
|
+
/* do column contextmenu handler */
|
24
|
+
if (column) {
|
25
|
+
var { contextmenu } = column.handlers
|
26
|
+
contextmenu && contextmenu(this.columns, this.data, column, record, rowIndex, target, e)
|
27
|
+
}
|
28
|
+
|
29
|
+
/* do rows contextmenu handler */
|
30
|
+
var { contextmenu: rowsContextMenu } = this.config.rows.handlers
|
31
|
+
rowsContextMenu && rowsContextMenu(this.columns, this.data, column, record, rowIndex, target, e)
|
32
|
+
}
|
@@ -33,10 +33,10 @@ export async function dataGridBodyDblclickHandler(this: DataGridBody, e: Event):
|
|
33
33
|
/* do column dblclick handler */
|
34
34
|
if (column) {
|
35
35
|
var { dblclick } = column.handlers
|
36
|
-
dblclick && dblclick(this.columns, this.data, column, record, rowIndex, target)
|
36
|
+
dblclick && dblclick(this.columns, this.data, column, record, rowIndex, target, e)
|
37
37
|
}
|
38
38
|
|
39
39
|
/* do rows dblclick handler */
|
40
40
|
var { dblclick: rowsDblclick } = this.config.rows.handlers
|
41
|
-
rowsDblclick && rowsDblclick(this.columns, this.data, column, record, rowIndex, target)
|
41
|
+
rowsDblclick && rowsDblclick(this.columns, this.data, column, record, rowIndex, target, e)
|
42
42
|
}
|
@@ -15,10 +15,10 @@ export async function dataGridBodyFocusChangeHandler(this: DataGridBody, e: Even
|
|
15
15
|
/* do column focus handler */
|
16
16
|
if (column) {
|
17
17
|
var { focus } = column.handlers
|
18
|
-
focus && focus(this.columns, this.data, column, record, rowIndex, target)
|
18
|
+
focus && focus(this.columns, this.data, column, record, rowIndex, target, e)
|
19
19
|
}
|
20
20
|
|
21
21
|
/* do rows focus handler */
|
22
22
|
var { focus: rowsFocus } = this.config.rows.handlers
|
23
|
-
rowsFocus && rowsFocus(this.columns, this.data, column, record, rowIndex, target)
|
23
|
+
rowsFocus && rowsFocus(this.columns, this.data, column, record, rowIndex, target, e)
|
24
24
|
}
|
package/src/data-manipulator.ts
CHANGED
@@ -15,8 +15,8 @@ import {
|
|
15
15
|
export class DataManipulator extends LitElement {
|
16
16
|
@property({ type: Object }) config: GristConfig = ZERO_CONFIG
|
17
17
|
@property({ type: Object }) data: GristData = ZERO_DATA
|
18
|
-
@property({ type:
|
19
|
-
@property({ type:
|
18
|
+
@property({ type: Array }) sorters: SortersConfig = []
|
19
|
+
@property({ type: Array }) filters: FilterValue[] = []
|
20
20
|
@property({ type: Object }) pagination: PaginationConfig = {}
|
21
21
|
|
22
22
|
constructor() {
|
@@ -64,6 +64,8 @@ export class DataManipulator extends LitElement {
|
|
64
64
|
})
|
65
65
|
|
66
66
|
/* tree processing */
|
67
|
+
this.addEventListener('collapse-all', (e: Event) => this.onCollapseAll(e as CustomEvent))
|
68
|
+
this.addEventListener('expand-all', (e: Event) => this.onExpandAll(e as CustomEvent))
|
67
69
|
this.addEventListener('collapsed', (e: Event) => this.onCollapsed(e as CustomEvent))
|
68
70
|
this.addEventListener('expanded', (e: Event) => this.onExpanded(e as CustomEvent))
|
69
71
|
this.addEventListener('check-in-tree', (e: Event) => this.onCheckInTree(e as CustomEvent))
|
@@ -213,6 +215,14 @@ export class DataManipulator extends LitElement {
|
|
213
215
|
this.requestUpdate()
|
214
216
|
}
|
215
217
|
|
218
|
+
onCollapseAll(e: CustomEvent) {
|
219
|
+
this.refresh(false)
|
220
|
+
}
|
221
|
+
|
222
|
+
onExpandAll(e: CustomEvent) {
|
223
|
+
this.refresh(true)
|
224
|
+
}
|
225
|
+
|
216
226
|
onCollapsed(e: CustomEvent) {
|
217
227
|
const record = e.detail
|
218
228
|
record.__expanded__ = false
|
@@ -228,8 +238,6 @@ export class DataManipulator extends LitElement {
|
|
228
238
|
}
|
229
239
|
|
230
240
|
onCheckInTree(e: CustomEvent) {
|
231
|
-
const self = this
|
232
|
-
|
233
241
|
function walkTreeCheckedUpdate(record: GristRecord, checked: 'checked' | 'unchecked') {
|
234
242
|
const children = record.__children__
|
235
243
|
|
@@ -287,7 +295,7 @@ export class DataManipulator extends LitElement {
|
|
287
295
|
* Therefore, it will be deprecated.
|
288
296
|
* @method
|
289
297
|
*/
|
290
|
-
refresh() {
|
298
|
+
refresh(forceExpandOrCollapse?: boolean) {
|
291
299
|
/*
|
292
300
|
- TODO 여기에서 TREE 형태 데이터의 접고, 펴는 것을 재구성한다.
|
293
301
|
- 동적으로 서브항목을 fetch 하는 기능은 제공하지 않는다.
|
@@ -302,15 +310,24 @@ export class DataManipulator extends LitElement {
|
|
302
310
|
) /* __depth__ 가 설정되지 않았거나, 0 인 경우만 수집 */
|
303
311
|
this.data = {
|
304
312
|
...this.data,
|
305
|
-
records: ([] as GristRecord[]).concat(
|
313
|
+
records: ([] as GristRecord[]).concat(
|
314
|
+
...toplevelRecords.map(record => this.traverseRefresh(record, forceExpandOrCollapse))
|
315
|
+
)
|
306
316
|
}
|
307
317
|
}
|
308
318
|
|
309
|
-
private traverseRefresh(record: GristRecord): GristRecord[] {
|
319
|
+
private traverseRefresh(record: GristRecord, forceExpandOrCollapse?: boolean): GristRecord[] {
|
320
|
+
if (forceExpandOrCollapse !== undefined) {
|
321
|
+
record = {
|
322
|
+
...record,
|
323
|
+
__expanded__: forceExpandOrCollapse
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
310
327
|
const { __expanded__, __children__ = [] } = record
|
311
328
|
|
312
329
|
if (__expanded__ && __children__.length > 0) {
|
313
|
-
return [record].concat(...__children__.map(child => this.traverseRefresh(child)))
|
330
|
+
return [record].concat(...__children__.map(child => this.traverseRefresh(child, forceExpandOrCollapse)))
|
314
331
|
} else {
|
315
332
|
return [record]
|
316
333
|
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import './ox-input-tree'
|
2
|
+
|
3
|
+
import { html, css } from 'lit'
|
4
|
+
import { customElement, query } from 'lit/decorators.js'
|
5
|
+
|
6
|
+
import { OxGristEditor } from './ox-grist-editor.js'
|
7
|
+
|
8
|
+
@customElement('ox-grist-editor-tree')
|
9
|
+
export class OxGristEditorTree extends OxGristEditor {
|
10
|
+
static styles = [
|
11
|
+
css`
|
12
|
+
:host {
|
13
|
+
flex: 1;
|
14
|
+
}
|
15
|
+
|
16
|
+
ox-input-tree {
|
17
|
+
flex: 1;
|
18
|
+
}
|
19
|
+
`
|
20
|
+
]
|
21
|
+
|
22
|
+
get editorTemplate() {
|
23
|
+
var { selectable } = this.column.record.options || {}
|
24
|
+
|
25
|
+
return html`<ox-input-tree .value=${this.value} .record=${this.record} ?selectable=${selectable}></ox-input-tree>`
|
26
|
+
}
|
27
|
+
}
|
@@ -91,6 +91,10 @@ export class OxGristEditor extends LitElement {
|
|
91
91
|
return this.renderRoot.firstElementChild as HTMLElement
|
92
92
|
}
|
93
93
|
|
94
|
+
get directEditable() {
|
95
|
+
return true
|
96
|
+
}
|
97
|
+
|
94
98
|
async firstUpdated() {
|
95
99
|
this.renderRoot.addEventListener('change', this._onchange.bind(this))
|
96
100
|
this.renderRoot.addEventListener('focusout', this._onfocusout.bind(this))
|
@@ -0,0 +1,226 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright © HatioLab Inc. All rights reserved.
|
3
|
+
*/
|
4
|
+
|
5
|
+
import { PropertyValues, css, html, nothing } from 'lit'
|
6
|
+
import { customElement, property, query, state } from 'lit/decorators.js'
|
7
|
+
import { ifDefined } from 'lit/directives/if-defined.js'
|
8
|
+
|
9
|
+
import { OxFormField } from '@operato/input'
|
10
|
+
import { GristRecord } from '../types'
|
11
|
+
|
12
|
+
@customElement('ox-input-tree')
|
13
|
+
export class OxInputTree extends OxFormField {
|
14
|
+
static styles = css`
|
15
|
+
:host {
|
16
|
+
overflow: hidden;
|
17
|
+
}
|
18
|
+
|
19
|
+
div[wrap] {
|
20
|
+
flex: 1;
|
21
|
+
|
22
|
+
position: relative;
|
23
|
+
|
24
|
+
display: flex;
|
25
|
+
align-items: center;
|
26
|
+
gap: 6px;
|
27
|
+
|
28
|
+
padding-left: calc(var(--tree-depth, 0) * 18px);
|
29
|
+
}
|
30
|
+
|
31
|
+
span[expander] {
|
32
|
+
display: inline-block;
|
33
|
+
vertical-align: middle;
|
34
|
+
width: 12px;
|
35
|
+
height: 20px;
|
36
|
+
cursor: pointer;
|
37
|
+
position: relative;
|
38
|
+
}
|
39
|
+
|
40
|
+
span[expander][collapsed]::before {
|
41
|
+
position: absolute;
|
42
|
+
top: 50%;
|
43
|
+
left: 50%;
|
44
|
+
transform: translate(-25%, -50%) rotate(-90deg);
|
45
|
+
content: ' ';
|
46
|
+
border: 5px solid transparent;
|
47
|
+
border-top: 5px solid var(--primary-color, #1890ff);
|
48
|
+
}
|
49
|
+
|
50
|
+
span[expander][expanded]::before {
|
51
|
+
position: absolute;
|
52
|
+
top: 50%;
|
53
|
+
left: 50%;
|
54
|
+
transform: translate(-50%, -25%);
|
55
|
+
content: ' ';
|
56
|
+
border: 5px solid transparent;
|
57
|
+
border-top: 5px solid var(--primary-color, #1890ff);
|
58
|
+
}
|
59
|
+
|
60
|
+
span[checkbox] {
|
61
|
+
display: inline-block;
|
62
|
+
vertical-align: middle;
|
63
|
+
width: 12px;
|
64
|
+
height: 20px;
|
65
|
+
cursor: pointer;
|
66
|
+
position: relative;
|
67
|
+
}
|
68
|
+
|
69
|
+
span[checkbox]::before {
|
70
|
+
cursor: pointer;
|
71
|
+
position: absolute;
|
72
|
+
top: 50%;
|
73
|
+
left: 50%;
|
74
|
+
transform: translate(-50%, -50%);
|
75
|
+
content: ' ';
|
76
|
+
display: block;
|
77
|
+
width: 10px;
|
78
|
+
height: 10px;
|
79
|
+
border: 1px solid var(--primary-color, #1890ff);
|
80
|
+
border-radius: 2px;
|
81
|
+
}
|
82
|
+
|
83
|
+
span[checkbox][checked='checked']::before {
|
84
|
+
background-color: var(--primary-color, #1890ff);
|
85
|
+
border-color: var(--primary-color, #1890ff);
|
86
|
+
}
|
87
|
+
|
88
|
+
span[checkbox][checked='checked']::after {
|
89
|
+
position: absolute;
|
90
|
+
content: ' ';
|
91
|
+
display: block;
|
92
|
+
top: 50%;
|
93
|
+
left: 50%;
|
94
|
+
width: 3px;
|
95
|
+
height: 7px;
|
96
|
+
border: 2px solid #fff;
|
97
|
+
border-top: none;
|
98
|
+
border-left: none;
|
99
|
+
-webkit-transform: translate(-50%, -50%) rotate(45deg);
|
100
|
+
-ms-transform: translate(-50%, -50%) rotate(45deg);
|
101
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
102
|
+
}
|
103
|
+
|
104
|
+
span[checkbox][checked='half-checked']::before {
|
105
|
+
background-color: var(--primary-color, #1890ff);
|
106
|
+
border-color: var(--primary-color, #1890ff);
|
107
|
+
}
|
108
|
+
|
109
|
+
span[checkbox][checked='half-checked']::after {
|
110
|
+
position: absolute;
|
111
|
+
content: ' ';
|
112
|
+
display: block;
|
113
|
+
top: 50%;
|
114
|
+
left: 50%;
|
115
|
+
transform: translate(-50%, -50%);
|
116
|
+
width: 10px;
|
117
|
+
height: 2px;
|
118
|
+
background-color: #fff;
|
119
|
+
}
|
120
|
+
|
121
|
+
span[label] {
|
122
|
+
flex: 1;
|
123
|
+
}
|
124
|
+
|
125
|
+
input {
|
126
|
+
width: 100%;
|
127
|
+
height: 100%;
|
128
|
+
border: 0;
|
129
|
+
background-color: transparent;
|
130
|
+
box-sizing: border-box;
|
131
|
+
}
|
132
|
+
|
133
|
+
input:focus {
|
134
|
+
outline: none;
|
135
|
+
}
|
136
|
+
`
|
137
|
+
|
138
|
+
@property({ type: Object }) record!: GristRecord
|
139
|
+
@property({ type: Boolean }) selectable?: boolean
|
140
|
+
|
141
|
+
@state() private checked?: 'checked' | 'half-checked' | 'unchecked'
|
142
|
+
@state() private expanded?: boolean = false
|
143
|
+
|
144
|
+
@query('input') input!: HTMLInputElement
|
145
|
+
|
146
|
+
render() {
|
147
|
+
var { __children__ } = this.record
|
148
|
+
|
149
|
+
const expandable = __children__ && __children__.length > 0
|
150
|
+
|
151
|
+
return html`
|
152
|
+
<div wrap>
|
153
|
+
${expandable
|
154
|
+
? html`
|
155
|
+
<span
|
156
|
+
expander
|
157
|
+
@click=${this.onClickExpander.bind(this)}
|
158
|
+
?expanded=${this.expanded}
|
159
|
+
?collapsed=${!this.expanded}
|
160
|
+
></span>
|
161
|
+
`
|
162
|
+
: html`<span expander></span>`}
|
163
|
+
${this.selectable
|
164
|
+
? html` <span checkbox @click=${this.onClickCheckbox.bind(this)} checked=${ifDefined(this.checked)}></span>`
|
165
|
+
: nothing}
|
166
|
+
|
167
|
+
<span label
|
168
|
+
><input
|
169
|
+
value=${ifDefined(this.value)}
|
170
|
+
@change=${(e: Event) => {
|
171
|
+
e.stopPropagation()
|
172
|
+
this.value = (e.target as HTMLInputElement).value
|
173
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
|
174
|
+
}}
|
175
|
+
focus
|
176
|
+
/></span>
|
177
|
+
|
178
|
+
<!-- <span label>${this.value}</span> -->
|
179
|
+
</div>
|
180
|
+
`
|
181
|
+
}
|
182
|
+
|
183
|
+
updated(changes: PropertyValues<this>) {
|
184
|
+
var { __depth__, __check_in_tree__, __expanded__ } = this.record
|
185
|
+
this.checked = __check_in_tree__
|
186
|
+
this.expanded = __expanded__
|
187
|
+
|
188
|
+
this.style.setProperty('--tree-depth', String(__depth__))
|
189
|
+
}
|
190
|
+
|
191
|
+
focus() {
|
192
|
+
this.input.focus()
|
193
|
+
}
|
194
|
+
|
195
|
+
select() {
|
196
|
+
this.input.select()
|
197
|
+
}
|
198
|
+
|
199
|
+
onClickCheckbox(e: MouseEvent) {
|
200
|
+
e.stopPropagation()
|
201
|
+
|
202
|
+
this.dispatchEvent(
|
203
|
+
new CustomEvent('check-in-tree', {
|
204
|
+
bubbles: true,
|
205
|
+
composed: true,
|
206
|
+
detail: this.record
|
207
|
+
})
|
208
|
+
)
|
209
|
+
|
210
|
+
this.requestUpdate()
|
211
|
+
}
|
212
|
+
|
213
|
+
onClickExpander(e: MouseEvent) {
|
214
|
+
e.stopPropagation()
|
215
|
+
|
216
|
+
this.dispatchEvent(
|
217
|
+
new CustomEvent(this.record.__expanded__ ? 'collapsed' : 'expanded', {
|
218
|
+
bubbles: true,
|
219
|
+
composed: true,
|
220
|
+
detail: this.record
|
221
|
+
})
|
222
|
+
)
|
223
|
+
|
224
|
+
this.requestUpdate()
|
225
|
+
}
|
226
|
+
}
|
package/src/editors/registry.ts
CHANGED
@@ -17,6 +17,7 @@ import { OxGristEditorTel } from './ox-grist-editor-tel'
|
|
17
17
|
import { OxGristEditorText } from './ox-grist-editor-text'
|
18
18
|
import { OxGristEditorTextarea } from './ox-grist-editor-textarea'
|
19
19
|
import { OxGristEditorTime } from './ox-grist-editor-time'
|
20
|
+
import { OxGristEditorTree } from './ox-grist-editor-tree'
|
20
21
|
import { OxGristEditorWeek } from './ox-grist-editor-week'
|
21
22
|
|
22
23
|
var EDITORS: { [name: string]: { new (): OxGristEditor } } = {
|
@@ -42,7 +43,8 @@ var EDITORS: { [name: string]: { new (): OxGristEditor } } = {
|
|
42
43
|
link: OxGristEditorText,
|
43
44
|
image: OxGristEditorImage,
|
44
45
|
file: OxGristEditorFile,
|
45
|
-
'string[]': OxGristEditorMultipleSelect
|
46
|
+
'string[]': OxGristEditorMultipleSelect,
|
47
|
+
tree: OxGristEditorTree
|
46
48
|
}
|
47
49
|
|
48
50
|
export function registerEditor(type: string, editor: { new (): OxGristEditor }) {
|