@operato/data-grist 8.2.22 → 8.2.24
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 +22 -0
- package/dist/src/data-grid/data-grid-body-style.js +1 -1
- package/dist/src/data-grid/data-grid-body-style.js.map +1 -1
- package/dist/src/data-grid/data-grid-body.d.ts +1 -15
- package/dist/src/data-grid/data-grid-body.js +49 -274
- package/dist/src/data-grid/data-grid-body.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-keydown-handler.js +5 -36
- package/dist/src/data-grid/event-handlers/data-grid-body-keydown-handler.js.map +1 -1
- package/dist/src/editors/ox-grist-editor.js +0 -3
- package/dist/src/editors/ox-grist-editor.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [8.2.24](https://github.com/hatiolab/operato/compare/v8.2.21...v8.2.24) (2026-04-14)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* 그리드 복붙시 태그 제거 ([066f0d8](https://github.com/hatiolab/operato/commit/066f0d835f43f588f5bc3c677717c1cad1f8f832))
|
|
12
|
+
* 그리드 복붙시 태그 제거 ([a2c572c](https://github.com/hatiolab/operato/commit/a2c572c6f056744f1599bc61967364e273b77236))
|
|
13
|
+
* 그리드 셀 ime-buffer로 한글 입력시 composing 유지 ([690464f](https://github.com/hatiolab/operato/commit/690464f0ae8dddbf94612c573a6a6be8dc51fcea))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### [8.2.23](https://github.com/hatiolab/operato/compare/v8.2.22...v8.2.23) (2026-04-14)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### :bug: Bug Fix
|
|
21
|
+
|
|
22
|
+
* 모바일 포커스 시 바로 선택이 아니라 드래그 인지 판단 ([3c4b89c](https://github.com/hatiolab/operato/commit/3c4b89c301200349ab779f3bc74cf8169b807264))
|
|
23
|
+
* 테블릿에서 롱 클릭시 복사 나오도록 수정 ([ad300b7](https://github.com/hatiolab/operato/commit/ad300b7c9bdc79bf5d892211e9cb84f273662def))
|
|
24
|
+
* 포커스시 textarea 클릭되는 현상 수정 ([fa54e2c](https://github.com/hatiolab/operato/commit/fa54e2cbdbf4fff6488b9610f18839f91708ce40))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
### [8.2.22](https://github.com/hatiolab/operato/compare/v8.2.21...v8.2.22) (2026-04-10)
|
|
7
29
|
|
|
8
30
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-grid-body-style.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-body-style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGnC,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport const dataGridBodyStyle = css`\n :host {\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n grid-auto-rows: var(--grid-record-height, min-content);\n\n overflow: auto;\n outline: none;\n color: var(--grid-record-color);\n position: relative;\n border-bottom: var(--grid-body-bottom-border);\n }\n\n ox-grid-field[odd] {\n background-color: var(--grid-record-odd-background-color);\n }\n\n ox-grid-field[disabled] {\n background-color: var(--grid-record-disabled-background-color, var(--grid-record-background-color));\n color: var(--grid-record-disabled-color, var(--grid-record-color));\n opacity: var(--grid-record-disabled-opacity, 1);\n }\n ox-grid-field[odd][disabled] {\n background-color: var(\n --grid-odd-record-disabled-background-color,\n var(--grid-record-disabled-background-color, var(--grid-record-odd-background-color))\n );\n color: var(--grid-odd-record-disabled-color, var(--grid-record-disabled-color, var(--grid-record-color)));\n opacity: var(--grid-odd-record-disabled-opacity, var(--grid-record-disabled-opacity, 1));\n }\n\n ox-grid-field[selected-row] {\n background-color: var(--grid-record-selected-background-color);\n color: var(--grid-record-selected-color);\n }\n\n ox-grid-field[focused-row] {\n box-shadow: var(--grid-record-focused-box-shadow);\n font-weight: bold;\n color: var(--grid-record-focused-color);\n background-image: var(--focused-background-image);\n background-blend-mode: darken;\n }\n\n ox-grid-field[focused] {\n border: var(--grid-record-focused-cell-border);\n }\n\n ox-grid-field[emphasized-row],\n ox-grid-field[emphasized-row][focused] {\n background-color: var(--grid-record-emphasized-background-color) !important;\n color: var(--grid-record-emphasized-color) !important;\n }\n\n
|
|
1
|
+
{"version":3,"file":"data-grid-body-style.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-body-style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGnC,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport const dataGridBodyStyle = css`\n :host {\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n grid-auto-rows: var(--grid-record-height, min-content);\n\n overflow: auto;\n outline: none;\n color: var(--grid-record-color);\n position: relative;\n border-bottom: var(--grid-body-bottom-border);\n }\n\n ox-grid-field[odd] {\n background-color: var(--grid-record-odd-background-color);\n }\n\n ox-grid-field[disabled] {\n background-color: var(--grid-record-disabled-background-color, var(--grid-record-background-color));\n color: var(--grid-record-disabled-color, var(--grid-record-color));\n opacity: var(--grid-record-disabled-opacity, 1);\n }\n ox-grid-field[odd][disabled] {\n background-color: var(\n --grid-odd-record-disabled-background-color,\n var(--grid-record-disabled-background-color, var(--grid-record-odd-background-color))\n );\n color: var(--grid-odd-record-disabled-color, var(--grid-record-disabled-color, var(--grid-record-color)));\n opacity: var(--grid-odd-record-disabled-opacity, var(--grid-record-disabled-opacity, 1));\n }\n\n ox-grid-field[selected-row] {\n background-color: var(--grid-record-selected-background-color);\n color: var(--grid-record-selected-color);\n }\n\n ox-grid-field[focused-row] {\n box-shadow: var(--grid-record-focused-box-shadow);\n font-weight: bold;\n color: var(--grid-record-focused-color);\n background-image: var(--focused-background-image);\n background-blend-mode: darken;\n }\n\n ox-grid-field[focused] {\n border: var(--grid-record-focused-cell-border);\n }\n\n ox-grid-field[emphasized-row],\n ox-grid-field[emphasized-row][focused] {\n background-color: var(--grid-record-emphasized-background-color) !important;\n color: var(--grid-record-emphasized-color) !important;\n }\n\n [editing] {\n background-color: var(--grid-record-editing-background-color);\n }\n\n @media print {\n :host {\n grid-template-columns: var(--grid-template-print-columns);\n }\n ox-grid-field[focused] {\n border: none;\n }\n\n ox-grid-field[selected-row] {\n background-color: transparent;\n }\n\n ox-grid-field[emphasized-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[focused-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[editing] {\n background-color: transparent;\n }\n }\n\n @media (prefers-color-scheme: dark) {\n ox-grid-field[focused-row] {\n background-blend-mode: lighten;\n }\n }\n\n @media (prefers-color-scheme: light) {\n ox-grid-field[focused-row] {\n background-blend-mode: darken;\n }\n }\n`\n"]}
|
|
@@ -32,9 +32,6 @@ export declare class DataGridBody extends LitElement {
|
|
|
32
32
|
private _recordViewRow?;
|
|
33
33
|
private _draggable?;
|
|
34
34
|
private _gridElement?;
|
|
35
|
-
private _imeBuffer?;
|
|
36
|
-
_imeComposing: boolean;
|
|
37
|
-
_imeEditing: boolean;
|
|
38
35
|
resetEdit(): void;
|
|
39
36
|
handleOnScroll(e: WheelEvent): void;
|
|
40
37
|
render(): import("lit-html").TemplateResult<1>;
|
|
@@ -51,20 +48,9 @@ export declare class DataGridBody extends LitElement {
|
|
|
51
48
|
row: number;
|
|
52
49
|
record: GristRecord;
|
|
53
50
|
}): void;
|
|
54
|
-
getSelectedBlockValues():
|
|
55
|
-
html: string;
|
|
56
|
-
text: string;
|
|
57
|
-
} | undefined;
|
|
51
|
+
getSelectedBlockValues(): Array<Array<any>> | any | undefined;
|
|
58
52
|
copy(): Promise<void>;
|
|
59
53
|
paste(): Promise<void>;
|
|
60
54
|
setSelectBlock(start?: DataGridField, end?: DataGridField): void;
|
|
61
55
|
buildAccumulatorRecord(): GristRecord;
|
|
62
|
-
/** IME buffer를 포커스된 셀 위에 위치시킨다 */
|
|
63
|
-
private _positionIMEBuffer;
|
|
64
|
-
/** IME buffer 값을 field-change 이벤트로 커밋한다 */
|
|
65
|
-
_commitIMEBuffer(row: number, column: number): void;
|
|
66
|
-
/** IME buffer 취소 (값 버리기) */
|
|
67
|
-
_discardIMEBuffer(): void;
|
|
68
|
-
/** IME buffer 초기화 */
|
|
69
|
-
private _resetIMEBuffer;
|
|
70
56
|
}
|
|
@@ -55,8 +55,6 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
55
55
|
this.from = -1;
|
|
56
56
|
this.to = -1;
|
|
57
57
|
this.fixedLefts = [];
|
|
58
|
-
this._imeComposing = false;
|
|
59
|
-
this._imeEditing = false;
|
|
60
58
|
// 검색시 스크롤 맨 위로
|
|
61
59
|
this._onFetchParamsChange = () => {
|
|
62
60
|
this.scrollTop = 0;
|
|
@@ -158,7 +156,6 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
158
156
|
`
|
|
159
157
|
: nothing}
|
|
160
158
|
${start && end && start !== end ? html ` <div select-block></div> ` : html ``}
|
|
161
|
-
<input id="ime-buffer" type="text" />
|
|
162
159
|
<slot></slot>
|
|
163
160
|
`;
|
|
164
161
|
}
|
|
@@ -167,43 +164,12 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
167
164
|
// this.addEventListener('scroll', this.handleOnScroll.bind(this))
|
|
168
165
|
/* focus() 를 받을 수 있도록 함. */
|
|
169
166
|
this.setAttribute('tabindex', '-1');
|
|
170
|
-
/* 한글 IME composition을 위한 숨겨진 input 버퍼 설정 */
|
|
171
|
-
const imeBuffer = this.renderRoot.querySelector('#ime-buffer');
|
|
172
|
-
this._imeBuffer = imeBuffer;
|
|
173
|
-
imeBuffer.addEventListener('compositionstart', () => {
|
|
174
|
-
this._imeComposing = true;
|
|
175
|
-
this._imeEditing = true;
|
|
176
|
-
imeBuffer.classList.add('active');
|
|
177
|
-
this._positionIMEBuffer();
|
|
178
|
-
});
|
|
179
|
-
imeBuffer.addEventListener('compositionend', () => {
|
|
180
|
-
this._imeComposing = false;
|
|
181
|
-
});
|
|
182
|
-
imeBuffer.addEventListener('input', () => {
|
|
183
|
-
if (!this._imeComposing && !this._imeEditing && imeBuffer.value) {
|
|
184
|
-
/* 영어/숫자: 실제 값이 입력된 경우에만 활성화 */
|
|
185
|
-
this._imeEditing = true;
|
|
186
|
-
imeBuffer.classList.add('active');
|
|
187
|
-
this._positionIMEBuffer();
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
167
|
/*
|
|
191
168
|
* focusout 으로 property를 변경시키는 경우, focusout에 의해 update가 발생하는 경우에는,
|
|
192
169
|
* 그리드 내부의 컴포넌트가 갱신되는 현상을 초래하게 된다.
|
|
193
170
|
* 따라서, focusout 핸들러에서 update를 유발하는 코드는 강력하게 금지시킨다.
|
|
194
171
|
*/
|
|
195
172
|
this.addEventListener('focusout', e => {
|
|
196
|
-
var _a;
|
|
197
|
-
/* IME buffer로 포커스가 이동하는 경우 keydown listener 유지 */
|
|
198
|
-
const related = e.relatedTarget;
|
|
199
|
-
if (related && ((_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(related))) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
/* 그리드 외부로 포커스 이동 시 IME buffer 커밋 */
|
|
203
|
-
if (this._imeEditing) {
|
|
204
|
-
const { row = 0, column = 0 } = this.focused || {};
|
|
205
|
-
this._commitIMEBuffer(row, column);
|
|
206
|
-
}
|
|
207
173
|
if (this._focusedListener) {
|
|
208
174
|
this.removeEventListener('keydown', this._focusedListener);
|
|
209
175
|
delete this._focusedListener;
|
|
@@ -237,18 +203,12 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
237
203
|
}
|
|
238
204
|
}));
|
|
239
205
|
});
|
|
240
|
-
this.renderRoot.addEventListener('
|
|
241
|
-
|
|
242
|
-
if (this._imeEditing) {
|
|
243
|
-
const { row = 0, column = 0 } = this.focused || {};
|
|
244
|
-
this._commitIMEBuffer(row, column);
|
|
245
|
-
}
|
|
206
|
+
this.renderRoot.addEventListener('mousedown', (event) => {
|
|
207
|
+
const e = event;
|
|
246
208
|
this.setSelectBlock();
|
|
247
|
-
if (
|
|
209
|
+
if (e.buttons !== 1) {
|
|
248
210
|
return;
|
|
249
211
|
}
|
|
250
|
-
e.preventDefault();
|
|
251
|
-
e.stopPropagation();
|
|
252
212
|
this._draggable = true;
|
|
253
213
|
var target = e.target.closest('ox-grid-field');
|
|
254
214
|
var { rowIndex, columnIndex } = target || {};
|
|
@@ -264,13 +224,11 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
264
224
|
this.startEditTarget(rowIndex, columnIndex);
|
|
265
225
|
}
|
|
266
226
|
});
|
|
267
|
-
this.renderRoot.addEventListener('
|
|
227
|
+
this.renderRoot.addEventListener('mousemove', (event) => {
|
|
268
228
|
const e = event;
|
|
269
|
-
if (
|
|
229
|
+
if (e.buttons !== 1 || !this._draggable) {
|
|
270
230
|
return;
|
|
271
231
|
}
|
|
272
|
-
e.preventDefault();
|
|
273
|
-
e.stopPropagation();
|
|
274
232
|
const field = e.target;
|
|
275
233
|
if (!this._selectBlock) {
|
|
276
234
|
this.setSelectBlock(this.focusedField || field, this.focusedField || field);
|
|
@@ -282,9 +240,7 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
282
240
|
this.setSelectBlock(start, end);
|
|
283
241
|
}
|
|
284
242
|
});
|
|
285
|
-
this.renderRoot.addEventListener('
|
|
286
|
-
event.preventDefault();
|
|
287
|
-
event.stopPropagation();
|
|
243
|
+
this.renderRoot.addEventListener('mouseup', (event) => {
|
|
288
244
|
this._draggable = false;
|
|
289
245
|
});
|
|
290
246
|
this.renderRoot.addEventListener('click', dataGridBodyClickHandler.bind(this));
|
|
@@ -336,8 +292,6 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
336
292
|
if (this.editTarget && this.editTarget.row == row && this.editTarget.column == column) {
|
|
337
293
|
return;
|
|
338
294
|
}
|
|
339
|
-
/* 에디터 편집 전환 시 IME buffer 정리 */
|
|
340
|
-
this._resetIMEBuffer();
|
|
341
295
|
this.editTarget = {
|
|
342
296
|
row,
|
|
343
297
|
column,
|
|
@@ -373,11 +327,6 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
373
327
|
if (left !== undefined) {
|
|
374
328
|
this.scrollLeft = left;
|
|
375
329
|
}
|
|
376
|
-
/* IME buffer 위치 업데이트 */
|
|
377
|
-
this._positionIMEBuffer();
|
|
378
|
-
if (!this.editTarget && this._imeBuffer) {
|
|
379
|
-
this._imeBuffer.focus();
|
|
380
|
-
}
|
|
381
330
|
}
|
|
382
331
|
// 페이징 바뀌면 스크롤 맨 위로
|
|
383
332
|
if (changes.has('data')) {
|
|
@@ -393,18 +342,7 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
393
342
|
}
|
|
394
343
|
}
|
|
395
344
|
focus() {
|
|
396
|
-
|
|
397
|
-
/* 에디터 편집 모드에서는 에디터가 자체적으로 포커스를 관리하므로 간섭하지 않는다 */
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
if (this._imeBuffer) {
|
|
401
|
-
/* 비편집 모드에서는 IME buffer로 포커스 리다이렉트 */
|
|
402
|
-
this._positionIMEBuffer();
|
|
403
|
-
this._imeBuffer.focus();
|
|
404
|
-
}
|
|
405
|
-
else {
|
|
406
|
-
super.focus();
|
|
407
|
-
}
|
|
345
|
+
super.focus();
|
|
408
346
|
if (this.focused === ZERO_FOCUS) {
|
|
409
347
|
let { records } = this.data;
|
|
410
348
|
let row = records.findIndex(record => record['__selected__']);
|
|
@@ -427,7 +365,6 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
427
365
|
delete this._recordViewRow;
|
|
428
366
|
});
|
|
429
367
|
}
|
|
430
|
-
/* 선택된 셀 블록의 값을 HTML(table)과 plain text(TSV) 두 가지 포맷으로 반환 */
|
|
431
368
|
getSelectedBlockValues() {
|
|
432
369
|
var { start, end } = this._selectBlock || {};
|
|
433
370
|
if (!(start && end)) {
|
|
@@ -441,81 +378,34 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
441
378
|
const endColumnIndex = start.columnIndex < end.columnIndex ? end.columnIndex : start.columnIndex;
|
|
442
379
|
const columnArray = new Array(endColumnIndex - startColumnIndex + 1).fill(startColumnIndex);
|
|
443
380
|
const columns = this.columns.filter(column => !column.hidden);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const htmlText = value === undefined || value === null ? '' : type == 'object' ? JSON.stringify(value) : value;
|
|
463
|
-
/* plainText: ① null/undefined → renderer ② object → name → renderer ③ 기타 → 값 그대로 */
|
|
464
|
-
let plainText = '';
|
|
465
|
-
if (value === undefined || value === null) {
|
|
466
|
-
/* 값이 없지만 renderer가 record의 다른 경로로 텍스트를 표시할 수 있음 */
|
|
467
|
-
if ((_a = column.record) === null || _a === void 0 ? void 0 : _a.renderer) {
|
|
468
|
-
try {
|
|
469
|
-
const r = column.record.renderer(value, column, record, rowIndex, null);
|
|
470
|
-
if (typeof r === 'string')
|
|
471
|
-
plainText = r;
|
|
472
|
-
}
|
|
473
|
-
catch (e) { }
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
else if (type == 'object') {
|
|
477
|
-
/* object: name 필드 우선, 없으면 renderer */
|
|
478
|
-
plainText = (value === null || value === void 0 ? void 0 : value.name) || '';
|
|
479
|
-
if (!plainText && ((_b = column.record) === null || _b === void 0 ? void 0 : _b.renderer)) {
|
|
480
|
-
try {
|
|
481
|
-
const r = column.record.renderer(value, column, record, rowIndex, null);
|
|
482
|
-
if (typeof r === 'string')
|
|
483
|
-
plainText = r;
|
|
484
|
-
}
|
|
485
|
-
catch (e) { }
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
else {
|
|
489
|
-
plainText = value;
|
|
490
|
-
}
|
|
491
|
-
return { type, htmlText, plainText };
|
|
492
|
-
});
|
|
493
|
-
return cells;
|
|
494
|
-
});
|
|
495
|
-
const html = '<table>' +
|
|
496
|
-
rows
|
|
497
|
-
.map(cells => '<tr>' +
|
|
498
|
-
cells
|
|
499
|
-
.map(c => c.type == 'object' && c.htmlText
|
|
500
|
-
? `<td type=${c.type} data-value="${String(c.htmlText).replace(/"/g, '"')}">${c.plainText}</td>`
|
|
501
|
-
: `<td type=${c.type}>${c.htmlText}</td>`)
|
|
502
|
-
.join('') +
|
|
503
|
-
'</tr>')
|
|
381
|
+
return ('<table>' +
|
|
382
|
+
new Array(endRowIndex - startRowIndex + 1)
|
|
383
|
+
.fill(startRowIndex)
|
|
384
|
+
.map((start, index) => {
|
|
385
|
+
const rowIndex = start + index;
|
|
386
|
+
const record = this.data.records[rowIndex];
|
|
387
|
+
const tds = columnArray
|
|
388
|
+
.map((start, index) => {
|
|
389
|
+
const columnIndex = start + index;
|
|
390
|
+
const column = columns[columnIndex];
|
|
391
|
+
const value = record === null || record === void 0 ? void 0 : record[column.name];
|
|
392
|
+
const type = typeof value;
|
|
393
|
+
const text = value === undefined || value === null ? '' : type == 'object' ? JSON.stringify(value) : value;
|
|
394
|
+
return `<td type=${type}>${text}</td>`;
|
|
395
|
+
})
|
|
396
|
+
.join('');
|
|
397
|
+
return `<tr>${tds}</tr>`;
|
|
398
|
+
})
|
|
504
399
|
.join('') +
|
|
505
|
-
'</table>';
|
|
506
|
-
/* 태그 없는 TSV 포맷 (object는 name만) */
|
|
507
|
-
const text = rows.map(cells => cells.map(c => String(c.plainText)).join('\t')).join('\n');
|
|
508
|
-
return { html, text };
|
|
400
|
+
'</table>');
|
|
509
401
|
}
|
|
510
402
|
}
|
|
511
403
|
async copy() {
|
|
512
404
|
const copied = this.getSelectedBlockValues();
|
|
513
|
-
if (!copied)
|
|
514
|
-
return;
|
|
515
405
|
await navigator.clipboard.write([
|
|
516
406
|
new ClipboardItem({
|
|
517
|
-
'text/html': new Blob([copied
|
|
518
|
-
'text/plain': new Blob([copied
|
|
407
|
+
'text/html': new Blob([copied], { type: 'text/html' }),
|
|
408
|
+
'text/plain': new Blob([copied], { type: 'text/plain' })
|
|
519
409
|
})
|
|
520
410
|
]);
|
|
521
411
|
const selectBlock = this.selectBlock || this.focusedField;
|
|
@@ -592,8 +482,8 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
592
482
|
const cells = record.querySelectorAll('td');
|
|
593
483
|
cells.forEach((item, columnIndex) => {
|
|
594
484
|
const targetColumn = columns[column + columnIndex];
|
|
595
|
-
|
|
596
|
-
let value =
|
|
485
|
+
let value = item.textContent;
|
|
486
|
+
// let value = item.textContent?.trim() as any
|
|
597
487
|
let type = targetColumn.type || item.getAttribute('type') || 'string';
|
|
598
488
|
type = type.includes('object') ? 'object' : type; // 오브젝트 타입 예외처리
|
|
599
489
|
let { editable } = targetColumn.record;
|
|
@@ -661,48 +551,31 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
661
551
|
});
|
|
662
552
|
return;
|
|
663
553
|
}
|
|
664
|
-
else if (type === 'text/plain') {
|
|
665
|
-
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
}
|
|
682
|
-
if (editable) {
|
|
683
|
-
this.dispatchEvent(new CustomEvent('field-change', {
|
|
684
|
-
bubbles: true,
|
|
685
|
-
composed: true,
|
|
686
|
-
detail: {
|
|
687
|
-
before: targetRecord[targetColumn.name],
|
|
688
|
-
after: cellValue || undefined,
|
|
689
|
-
column: targetColumn,
|
|
690
|
-
record: targetRecord,
|
|
691
|
-
row: targetRowIndex
|
|
692
|
-
}
|
|
693
|
-
}));
|
|
554
|
+
else if (!selection && type === 'text/plain') {
|
|
555
|
+
const targetRecord = records[row] || { __dirty__: '+' };
|
|
556
|
+
const targetColumn = columns[column];
|
|
557
|
+
let { editable } = targetColumn.record;
|
|
558
|
+
if (typeof editable === 'function') {
|
|
559
|
+
editable = editable.call(this, content, targetColumn, targetRecord, row, this);
|
|
560
|
+
}
|
|
561
|
+
if (targetColumn && !targetColumn.gutterName && editable) {
|
|
562
|
+
this.dispatchEvent(new CustomEvent('field-change', {
|
|
563
|
+
bubbles: true,
|
|
564
|
+
composed: true,
|
|
565
|
+
detail: {
|
|
566
|
+
before: targetRecord[targetColumn.name],
|
|
567
|
+
after: content,
|
|
568
|
+
column: targetColumn,
|
|
569
|
+
record: targetRecord,
|
|
570
|
+
row: row
|
|
694
571
|
}
|
|
695
|
-
});
|
|
696
|
-
}
|
|
572
|
+
}));
|
|
573
|
+
}
|
|
697
574
|
}
|
|
698
575
|
}
|
|
699
576
|
catch (e) {
|
|
700
577
|
console.log('e : ', e);
|
|
701
578
|
}
|
|
702
|
-
finally {
|
|
703
|
-
/* paste 완료 후 포커스를 그리드로 복원 */
|
|
704
|
-
this.focus();
|
|
705
|
-
}
|
|
706
579
|
}
|
|
707
580
|
setSelectBlock(start, end) {
|
|
708
581
|
var _a;
|
|
@@ -741,84 +614,12 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
|
741
614
|
return record;
|
|
742
615
|
}, {});
|
|
743
616
|
}
|
|
744
|
-
/** IME buffer를 포커스된 셀 위에 위치시킨다 */
|
|
745
|
-
_positionIMEBuffer() {
|
|
746
|
-
var _a;
|
|
747
|
-
const focusedEl = (_a = this.renderRoot) === null || _a === void 0 ? void 0 : _a.querySelector('[focused]');
|
|
748
|
-
if (focusedEl && this._imeBuffer) {
|
|
749
|
-
this._imeBuffer.style.left = focusedEl.offsetLeft + 'px';
|
|
750
|
-
this._imeBuffer.style.top = focusedEl.offsetTop + 'px';
|
|
751
|
-
this._imeBuffer.style.width = focusedEl.offsetWidth + 'px';
|
|
752
|
-
this._imeBuffer.style.height = focusedEl.offsetHeight + 'px';
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
/** IME buffer 값을 field-change 이벤트로 커밋한다 */
|
|
756
|
-
_commitIMEBuffer(row, column) {
|
|
757
|
-
var _a;
|
|
758
|
-
const text = (_a = this._imeBuffer) === null || _a === void 0 ? void 0 : _a.value;
|
|
759
|
-
this._resetIMEBuffer();
|
|
760
|
-
if (!text)
|
|
761
|
-
return;
|
|
762
|
-
const columns = this.columns.filter(c => !c.hidden);
|
|
763
|
-
const col = columns[column];
|
|
764
|
-
if (!col || col.gutterName)
|
|
765
|
-
return;
|
|
766
|
-
const record = this.data.records[row] || { __dirty__: '+' };
|
|
767
|
-
let { editable } = col.record;
|
|
768
|
-
if (typeof editable === 'function') {
|
|
769
|
-
editable = editable.call(this, record[col.name], col, record, row, this);
|
|
770
|
-
}
|
|
771
|
-
if (!editable)
|
|
772
|
-
return;
|
|
773
|
-
/* 타입에 따른 값 변환 */
|
|
774
|
-
let value = text;
|
|
775
|
-
switch (col.type) {
|
|
776
|
-
case 'number':
|
|
777
|
-
case 'float':
|
|
778
|
-
case 'integer':
|
|
779
|
-
case 'progress':
|
|
780
|
-
value = parseToNumberOrNull(text);
|
|
781
|
-
if (value === null)
|
|
782
|
-
return;
|
|
783
|
-
break;
|
|
784
|
-
case 'boolean':
|
|
785
|
-
case 'checkbox':
|
|
786
|
-
return; /* boolean은 키보드 텍스트 입력으로 편집 불가 */
|
|
787
|
-
}
|
|
788
|
-
this.dispatchEvent(new CustomEvent('field-change', {
|
|
789
|
-
bubbles: true,
|
|
790
|
-
composed: true,
|
|
791
|
-
detail: {
|
|
792
|
-
before: record[col.name],
|
|
793
|
-
after: value,
|
|
794
|
-
column: col,
|
|
795
|
-
record,
|
|
796
|
-
row
|
|
797
|
-
}
|
|
798
|
-
}));
|
|
799
|
-
}
|
|
800
|
-
/** IME buffer 취소 (값 버리기) */
|
|
801
|
-
_discardIMEBuffer() {
|
|
802
|
-
this._resetIMEBuffer();
|
|
803
|
-
}
|
|
804
|
-
/** IME buffer 초기화 */
|
|
805
|
-
_resetIMEBuffer() {
|
|
806
|
-
if (this._imeBuffer) {
|
|
807
|
-
this._imeBuffer.value = '';
|
|
808
|
-
this._imeBuffer.classList.remove('active');
|
|
809
|
-
}
|
|
810
|
-
this._imeEditing = false;
|
|
811
|
-
this._imeComposing = false;
|
|
812
|
-
}
|
|
813
617
|
};
|
|
814
618
|
DataGridBody.styles = [
|
|
815
619
|
dataGridBodyStyle,
|
|
816
620
|
css `
|
|
817
621
|
:host {
|
|
818
622
|
font-variation-settings: 'FILL' 1;
|
|
819
|
-
|
|
820
|
-
overscroll-behavior: none;
|
|
821
|
-
user-select: none;
|
|
822
623
|
}
|
|
823
624
|
|
|
824
625
|
[select-block] {
|
|
@@ -830,7 +631,6 @@ DataGridBody.styles = [
|
|
|
830
631
|
border: var(--grid-record-focused-cell-border);
|
|
831
632
|
background-image: var(--focused-background-image);
|
|
832
633
|
pointer-events: none;
|
|
833
|
-
|
|
834
634
|
z-index: 5;
|
|
835
635
|
}
|
|
836
636
|
|
|
@@ -863,31 +663,6 @@ DataGridBody.styles = [
|
|
|
863
663
|
box-shadow: none !important;
|
|
864
664
|
}
|
|
865
665
|
}
|
|
866
|
-
|
|
867
|
-
/* 한글 IME composition을 위한 숨겨진 input 버퍼 — 기존 에디터 셀 스타일과 일치 */
|
|
868
|
-
#ime-buffer {
|
|
869
|
-
position: absolute;
|
|
870
|
-
opacity: 0;
|
|
871
|
-
z-index: 10;
|
|
872
|
-
background-color: var(--grid-record-editing-background-color, var(--grid-record-background-color, #fff));
|
|
873
|
-
color: var(--md-sys-color-on-background, inherit);
|
|
874
|
-
font: inherit;
|
|
875
|
-
font-size: var(--grid-record-wide-fontsize);
|
|
876
|
-
border: 1px solid transparent;
|
|
877
|
-
border-width: 1px 0;
|
|
878
|
-
border-top: var(--grid-record-editing-border, none);
|
|
879
|
-
border-bottom: var(--grid-record-editing-border, none);
|
|
880
|
-
padding: var(--grid-record-padding);
|
|
881
|
-
box-sizing: border-box;
|
|
882
|
-
outline: none;
|
|
883
|
-
overflow: hidden;
|
|
884
|
-
pointer-events: none;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
#ime-buffer.active {
|
|
888
|
-
opacity: 1;
|
|
889
|
-
pointer-events: auto;
|
|
890
|
-
}
|
|
891
666
|
`
|
|
892
667
|
];
|
|
893
668
|
__decorate([
|