open-grid 0.3.2 → 1.0.0-rc.1

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 (55) hide show
  1. package/README.md +3 -2
  2. package/dist/OpenGrid-C6SK6VeK.cjs +90 -0
  3. package/dist/OpenGrid-C6SK6VeK.cjs.map +1 -0
  4. package/dist/OpenGrid-D7EJOVi1.js +4864 -0
  5. package/dist/OpenGrid-D7EJOVi1.js.map +1 -0
  6. package/dist/open-grid-base.css +14 -0
  7. package/dist/open-grid-react.cjs +1 -1
  8. package/dist/open-grid-react.js +1 -1
  9. package/dist/open-grid-vue.cjs +1 -1
  10. package/dist/open-grid-vue.js +1 -1
  11. package/dist/open-grid.cjs +6 -6
  12. package/dist/open-grid.cjs.map +1 -1
  13. package/dist/open-grid.js +224 -172
  14. package/dist/open-grid.js.map +1 -1
  15. package/dist/types/core/CellEditManager.d.ts +2 -3
  16. package/dist/types/core/CellEventHandler.d.ts +4 -5
  17. package/dist/types/core/CellTypeRegistry.d.ts +1 -2
  18. package/dist/types/core/ColumnLayout.d.ts +1 -2
  19. package/dist/types/core/ContextMenu.d.ts +1 -2
  20. package/dist/types/core/CrossGridMapper.d.ts +21 -0
  21. package/dist/types/core/CrossGridRegistry.d.ts +12 -0
  22. package/dist/types/core/DataLayer.d.ts +4 -2
  23. package/dist/types/core/DragVisuals.d.ts +23 -0
  24. package/dist/types/core/ExportManager.d.ts +4 -3
  25. package/dist/types/core/FilterPanel.d.ts +1 -2
  26. package/dist/types/core/FilterSelect.d.ts +1 -2
  27. package/dist/types/core/FindBarManager.d.ts +4 -5
  28. package/dist/types/core/FooterManager.d.ts +2 -1
  29. package/dist/types/core/FormulaEngine.d.ts +1 -2
  30. package/dist/types/core/GridRenderer.d.ts +3 -2
  31. package/dist/types/core/GridShuttle.d.ts +24 -0
  32. package/dist/types/core/GroupEngine.d.ts +7 -4
  33. package/dist/types/core/GroupTreeManager.d.ts +6 -3
  34. package/dist/types/core/KeyboardManager.d.ts +4 -5
  35. package/dist/types/core/OpenGrid.d.ts +55 -4
  36. package/dist/types/core/OverrideKernel.d.ts +70 -0
  37. package/dist/types/core/PivotEngine.d.ts +1 -2
  38. package/dist/types/core/RowDragDrop.d.ts +25 -5
  39. package/dist/types/core/RowManager.d.ts +0 -1
  40. package/dist/types/core/SortFilterManager.d.ts +5 -6
  41. package/dist/types/core/TriggerManager.d.ts +1 -2
  42. package/dist/types/core/WorksheetManager.d.ts +1 -2
  43. package/dist/types/core/editors/CellEditor.d.ts +2 -3
  44. package/dist/types/core/editors/DateEditor.d.ts +2 -3
  45. package/dist/types/core/editors/SelectEditor.d.ts +2 -3
  46. package/dist/types/core/renderers/CellRenderer.d.ts +15 -4
  47. package/dist/types/core/types.d.ts +115 -0
  48. package/dist/types/index.d.ts +3 -1
  49. package/dist/types/react/OpenGrid.d.ts +3 -3
  50. package/dist/types/vue/types.d.ts +1 -2
  51. package/package.json +99 -102
  52. package/dist/OpenGrid-CzP1mcZW.cjs +0 -90
  53. package/dist/OpenGrid-CzP1mcZW.cjs.map +0 -1
  54. package/dist/OpenGrid-Dult64jp.js +0 -4401
  55. package/dist/OpenGrid-Dult64jp.js.map +0 -1
@@ -1,4401 +0,0 @@
1
- class Ye {
2
- constructor() {
3
- this.listeners = /* @__PURE__ */ new Map();
4
- }
5
- on(e, t) {
6
- const s = this.listeners.get(e) ?? [];
7
- return s.push({ handler: t, once: !1 }), this.listeners.set(e, s), this;
8
- }
9
- once(e, t) {
10
- const s = this.listeners.get(e) ?? [];
11
- return s.push({ handler: t, once: !0 }), this.listeners.set(e, s), this;
12
- }
13
- off(e, t) {
14
- if (!t)
15
- return this.listeners.delete(e), this;
16
- const s = this.listeners.get(e);
17
- if (s) {
18
- const i = s.filter((n) => n.handler !== t);
19
- i.length === 0 ? this.listeners.delete(e) : this.listeners.set(e, i);
20
- }
21
- return this;
22
- }
23
- emit(e, ...t) {
24
- const s = this.listeners.get(e);
25
- if (!s || s.length === 0) return !1;
26
- const i = [];
27
- for (const n of s)
28
- n.handler(...t), n.once || i.push(n);
29
- return i.length !== s.length && (i.length === 0 ? this.listeners.delete(e) : this.listeners.set(e, i)), !0;
30
- }
31
- removeAllListeners(e) {
32
- return e ? this.listeners.delete(e) : this.listeners.clear(), this;
33
- }
34
- listenerCount(e) {
35
- var t;
36
- return ((t = this.listeners.get(e)) == null ? void 0 : t.length) ?? 0;
37
- }
38
- }
39
- let Xe = 0;
40
- function Me() {
41
- return `og-r-${++Xe}`;
42
- }
43
- class Ge {
44
- constructor(e = "_ogRowId") {
45
- this._data = [], this._original = [], this._meta = /* @__PURE__ */ new Map(), this._displayIndexes = [], this._idMap = /* @__PURE__ */ new Map(), this._findQuery = "", this._findFields = [], this._idField = e;
46
- }
47
- // ─── 데이터 설정 ──────────────────────────────────────
48
- setData(e) {
49
- this._data = e.map((t) => {
50
- const s = Me(), i = { ...t, [this._idField]: s };
51
- return this._meta.set(s, { state: "none", rowId: s }), i;
52
- }), this._original = this._data.map((t) => ({ ...t })), this._rebuildIdMap(), this._displayIndexes = this._data.map((t, s) => s);
53
- }
54
- getData() {
55
- return this._displayIndexes.map((e) => this._data[e]);
56
- }
57
- getOriginalData() {
58
- return [...this._original];
59
- }
60
- getAllData() {
61
- return [...this._data];
62
- }
63
- clearData() {
64
- this._data = [], this._original = [], this._meta.clear(), this._idMap.clear(), this._displayIndexes = [];
65
- }
66
- get rowCount() {
67
- return this._displayIndexes.length;
68
- }
69
- get totalRowCount() {
70
- return this._data.length;
71
- }
72
- // ─── 행 CRUD ──────────────────────────────────────────
73
- addRow(e, t = "last") {
74
- const s = Me(), i = { ...e, [this._idField]: s };
75
- if (this._meta.set(s, { state: "added", rowId: s }), t === "last") {
76
- const n = this._data.push(i) - 1;
77
- this._idMap.set(s, n), this._displayIndexes.push(n);
78
- } else if (t === "first")
79
- this._data.unshift(i), this._rebuildIdMap(), this._displayIndexes.unshift(0);
80
- else {
81
- const n = Math.min(t, this._displayIndexes.length), o = n < this._displayIndexes.length ? this._displayIndexes[n] : this._data.length;
82
- this._data.splice(o, 0, i), this._rebuildIdMap(), this._displayIndexes = this._data.map((l, r) => r);
83
- }
84
- }
85
- removeRow(e) {
86
- const t = this._displayIndexes[e];
87
- if (t === void 0) return;
88
- const s = this._data[t], i = s[this._idField], n = this._meta.get(i);
89
- return (n == null ? void 0 : n.state) === "added" ? (this._data.splice(t, 1), this._meta.delete(i)) : this._meta.set(i, { ...n, state: "removed" }), this._rebuildIdMap(), this._displayIndexes = this._data.map((o, l) => ({ r: o, i: l })).filter(({ r: o }) => {
90
- var l;
91
- return ((l = this._meta.get(o[this._idField])) == null ? void 0 : l.state) !== "removed";
92
- }).map(({ i: o }) => o), s;
93
- }
94
- moveRow(e, t) {
95
- const s = this._displayIndexes[e], i = this._displayIndexes[t];
96
- if (s === void 0 || i === void 0) return;
97
- const [n] = this._data.splice(s, 1), o = s < i ? i - 1 : i;
98
- this._data.splice(o, 0, n), this._rebuildIdMap(), this._displayIndexes = this._data.map((l, r) => ({ r: l, i: r })).filter(({ r: l }) => {
99
- var r;
100
- return ((r = this._meta.get(l[this._idField])) == null ? void 0 : r.state) !== "removed";
101
- }).map(({ i: l }) => l);
102
- }
103
- updateCell(e, t, s) {
104
- const i = this._displayIndexes[e];
105
- if (i === void 0) return !1;
106
- const o = this._data[i][this._idField], l = this._meta.get(o);
107
- return (l == null ? void 0 : l.state) === "none" && this._meta.set(o, {
108
- ...l,
109
- state: "edited",
110
- original: { ...this._original[i] }
111
- }), this._data[i][t] = s, !0;
112
- }
113
- getRowByIndex(e) {
114
- const t = this._displayIndexes[e];
115
- return t !== void 0 ? this._data[t] : void 0;
116
- }
117
- getCellValue(e, t) {
118
- var s;
119
- return (s = this.getRowByIndex(e)) == null ? void 0 : s[t];
120
- }
121
- // ─── 변경 추적 ────────────────────────────────────────
122
- /** 수정된 행만 반환 (추가/삭제 제외) */
123
- getEditedRows() {
124
- return this._data.filter(
125
- (e) => {
126
- var t;
127
- return ((t = this._meta.get(e[this._idField])) == null ? void 0 : t.state) === "edited";
128
- }
129
- );
130
- }
131
- /** 수정된 행만 반환 (하위 호환용 — 신규 코드는 getEditedRows() 사용) */
132
- getChangedRows() {
133
- return this.getEditedRows();
134
- }
135
- getAddedRows() {
136
- return this._data.filter(
137
- (e) => {
138
- var t;
139
- return ((t = this._meta.get(e[this._idField])) == null ? void 0 : t.state) === "added";
140
- }
141
- );
142
- }
143
- getRemovedRows() {
144
- return this._data.filter(
145
- (e) => {
146
- var t;
147
- return ((t = this._meta.get(e[this._idField])) == null ? void 0 : t.state) === "removed";
148
- }
149
- );
150
- }
151
- /**
152
- * 추가/수정/삭제 모든 변경사항을 한 번에 반환.
153
- * edited 행에는 _changedFields 배열도 포함.
154
- */
155
- getChanges() {
156
- const e = [], t = [], s = [];
157
- for (const i of this._data) {
158
- const n = i[this._idField], o = this._meta.get(n), l = (o == null ? void 0 : o.state) ?? "none";
159
- if (l === "added")
160
- e.push({ ...i });
161
- else if (l === "removed")
162
- s.push({ ...i });
163
- else if (l === "edited") {
164
- const r = o.original ?? {}, a = Object.keys(i).filter(
165
- (c) => c !== this._idField && i[c] !== r[c]
166
- );
167
- t.push({ ...i, _changedFields: a });
168
- }
169
- }
170
- return { added: e, edited: t, removed: s };
171
- }
172
- /**
173
- * 수정된 컬럼 정보 반환 — 각 edited 행에 대해 { row, fields, diff } 반환.
174
- * diff: { field, oldValue, newValue }[]
175
- */
176
- getChangedColumns() {
177
- return this._data.filter((e) => {
178
- var t;
179
- return ((t = this._meta.get(e[this._idField])) == null ? void 0 : t.state) === "edited";
180
- }).map((e) => {
181
- var i;
182
- const t = ((i = this._meta.get(e[this._idField])) == null ? void 0 : i.original) ?? {}, s = [];
183
- for (const n of Object.keys(e))
184
- n !== this._idField && e[n] !== t[n] && s.push({ field: n, oldValue: t[n], newValue: e[n] });
185
- return { row: { ...e }, fields: s.map((n) => n.field), diff: s };
186
- });
187
- }
188
- /** rowIndex 행의 원본(수정 전) 데이터 반환. 추가된 행은 undefined. */
189
- getOriginalRow(e) {
190
- const t = this._displayIndexes[e];
191
- if (t === void 0) return;
192
- const s = this._data[t], i = this._meta.get(s[this._idField]);
193
- if (!(!i || i.state === "added"))
194
- return i.state === "edited" && i.original ? { ...i.original } : { ...this._original[t] };
195
- }
196
- getRowsWithState(e) {
197
- return this._data.map((t) => {
198
- var i;
199
- const s = ((i = this._meta.get(t[this._idField])) == null ? void 0 : i.state) ?? "none";
200
- return { ...t, [e]: s };
201
- });
202
- }
203
- getRowState(e) {
204
- var s;
205
- const t = this.getRowByIndex(e);
206
- return t ? ((s = this._meta.get(t[this._idField])) == null ? void 0 : s.state) ?? "none" : "none";
207
- }
208
- // ─── 정렬 ─────────────────────────────────────────────
209
- applySort(e) {
210
- const t = (i) => {
211
- var n, o;
212
- return ((o = this._meta.get((n = this._data[i]) == null ? void 0 : n[this._idField])) == null ? void 0 : o.state) !== "removed";
213
- };
214
- if (e.length === 0) {
215
- this._displayIndexes = this._data.map((i, n) => n).filter(t);
216
- return;
217
- }
218
- const s = this._displayIndexes.filter(t).map((i) => {
219
- const n = this._data[i];
220
- return {
221
- idx: i,
222
- keys: e.map((o) => n[o.field])
223
- };
224
- });
225
- s.sort((i, n) => {
226
- for (let o = 0; o < e.length; o++) {
227
- const l = e[o].dir, r = i.keys[o], a = n.keys[o];
228
- let c = 0;
229
- if (r == null && a == null) c = 0;
230
- else if (r == null) c = -1;
231
- else if (a == null) c = 1;
232
- else if (typeof r == "number" && typeof a == "number") c = r - a;
233
- else {
234
- const h = String(r), u = String(a);
235
- c = h < u ? -1 : h > u ? 1 : 0;
236
- }
237
- if (c !== 0) return l === "asc" ? c : -c;
238
- }
239
- return 0;
240
- }), this._displayIndexes = s.map((i) => i.idx);
241
- }
242
- // ─── 필터 ─────────────────────────────────────────────
243
- applyFilter(e) {
244
- const t = Object.keys(e);
245
- this._displayIndexes = this._data.map((s, i) => ({ r: s, i })).filter(({ r: s }) => {
246
- var i;
247
- if (((i = this._meta.get(s[this._idField])) == null ? void 0 : i.state) === "removed" || t.length > 0 && !t.every((n) => {
248
- const o = s[n];
249
- return e[n].every((l) => Qe(o, l));
250
- }))
251
- return !1;
252
- if (this._findQuery && this._findFields.length > 0) {
253
- const n = this._findQuery;
254
- if (!this._findFields.some((l) => {
255
- const r = s[l];
256
- return r != null && String(r).toLowerCase().includes(n);
257
- })) return !1;
258
- }
259
- return !0;
260
- }).map(({ i: s }) => s);
261
- }
262
- /** F3: 찾기 바 전체 컬럼 OR 검색 설정 */
263
- setFindFilter(e, t) {
264
- this._findQuery = e.toLowerCase(), this._findFields = t;
265
- }
266
- // ─── 내부 유틸 ────────────────────────────────────────
267
- _rebuildIdMap() {
268
- this._idMap.clear(), this._data.forEach((e, t) => {
269
- this._idMap.set(e[this._idField], t);
270
- });
271
- }
272
- }
273
- function Qe(d, e) {
274
- const t = d, s = e.value;
275
- switch (e.operator) {
276
- case "=":
277
- return t == s;
278
- case "!=":
279
- return t != s;
280
- case ">":
281
- return t > s;
282
- case ">=":
283
- return t >= s;
284
- case "<":
285
- return t < s;
286
- case "<=":
287
- return t <= s;
288
- case "contains":
289
- return String(t).includes(String(s));
290
- case "startsWith":
291
- return String(t).startsWith(String(s));
292
- case "endsWith":
293
- return String(t).endsWith(String(s));
294
- default:
295
- return !0;
296
- }
297
- }
298
- class Je {
299
- constructor(e, t) {
300
- this._totalRows = 0, this._scrollTop = 0, this._viewportHeight = 0, this._rafId = null, this._onScroll = () => {
301
- this._scrollTop = this.container.scrollTop, this._scheduleRender();
302
- }, this.container = e, this.rowHeight = t.rowHeight, this.overscan = t.overscan ?? 5, this.onRender = t.onRender, this.container.addEventListener("scroll", this._onScroll, { passive: !0 });
303
- }
304
- _scheduleRender() {
305
- this._rafId === null && (this._rafId = requestAnimationFrame(() => {
306
- this._rafId = null;
307
- const e = this.getVisibleRange();
308
- this.onRender(e.startIndex, e.endIndex);
309
- }));
310
- }
311
- getVisibleRange() {
312
- const e = Math.ceil(this._viewportHeight / this.rowHeight), t = Math.max(0, Math.floor(this._scrollTop / this.rowHeight) - this.overscan), s = Math.min(
313
- this._totalRows - 1,
314
- t + e + this.overscan * 2
315
- ), i = t * this.rowHeight;
316
- return { startIndex: t, endIndex: s, offsetY: i };
317
- }
318
- setTotalRows(e) {
319
- this._totalRows = e, this._updateSpacerHeight(), this._scheduleRender();
320
- }
321
- setViewportHeight(e) {
322
- this._viewportHeight = e, this._scheduleRender();
323
- }
324
- setRowHeight(e) {
325
- this.rowHeight = e, this._updateSpacerHeight(), this._scheduleRender();
326
- }
327
- scrollToRow(e) {
328
- const t = e * this.rowHeight, s = t + this.rowHeight, i = this._scrollTop + this._viewportHeight;
329
- if (t < this._scrollTop)
330
- this._scrollTop = t, this.container.scrollTop = t;
331
- else if (s > i) {
332
- const n = s - this._viewportHeight;
333
- this._scrollTop = n, this.container.scrollTop = n;
334
- }
335
- }
336
- getTotalHeight() {
337
- return this._totalRows * this.rowHeight;
338
- }
339
- _updateSpacerHeight() {
340
- const e = this.container.querySelector(".og-spacer");
341
- e && (e.style.height = `${this.getTotalHeight()}px`);
342
- }
343
- destroy() {
344
- this.container.removeEventListener("scroll", this._onScroll), this._rafId !== null && cancelAnimationFrame(this._rafId);
345
- }
346
- }
347
- class le {
348
- constructor(e, t = 0) {
349
- this._flatLeaves = [], this._maxDepth = 1, this._frozenCount = 0, this._columns = e, this._frozenCount = t, this._process();
350
- }
351
- _process() {
352
- const e = [];
353
- let t = 0;
354
- const s = (i, n) => {
355
- for (const o of i)
356
- o.children && o.children.length > 0 ? (s(o.children, n + 1), this._maxDepth = Math.max(this._maxDepth, n + 1)) : e.push({ ...o, _colIndex: t++, _depth: n, _leaf: !0 });
357
- };
358
- this._maxDepth = 1, s(this._columns, 1), this._flatLeaves = e;
359
- }
360
- get leaves() {
361
- return this._flatLeaves;
362
- }
363
- get visibleLeaves() {
364
- return this._flatLeaves.filter((e) => !e.hidden);
365
- }
366
- get headerDepth() {
367
- return this._maxDepth;
368
- }
369
- get frozenCount() {
370
- return this._frozenCount;
371
- }
372
- setFrozen(e) {
373
- this._frozenCount = e;
374
- }
375
- setColumns(e) {
376
- this._columns = e, this._process();
377
- }
378
- hideColumn(e) {
379
- const t = Array.isArray(e) ? e : [e];
380
- this._flatLeaves.forEach((s) => {
381
- t.includes(s.field) && (s.hidden = !0);
382
- });
383
- }
384
- showColumn(e) {
385
- const t = Array.isArray(e) ? e : [e];
386
- this._flatLeaves.forEach((s) => {
387
- t.includes(s.field) && (s.hidden = !1);
388
- });
389
- }
390
- addColumn(e, t = "last") {
391
- t === "last" ? this._columns.push(e) : t === "first" ? this._columns.unshift(e) : this._columns.splice(t, 0, e), this._process();
392
- }
393
- removeColumn(e) {
394
- const t = (s) => s.filter((i) => i.field === e ? !1 : (i.children && (i.children = t(i.children)), !0));
395
- this._columns = t(this._columns), this._process();
396
- }
397
- getColumnByField(e) {
398
- return this._flatLeaves.find((t) => t.field === e);
399
- }
400
- getColumnByIndex(e) {
401
- return this._flatLeaves[e];
402
- }
403
- getColumnIndex(e) {
404
- return this._flatLeaves.findIndex((t) => t.field === e);
405
- }
406
- /** 헤더 렌더링용 셀 계산 */
407
- buildHeaderCells() {
408
- const e = Array.from({ length: this._maxDepth }, () => []);
409
- let t = 0;
410
- const s = (i, n) => {
411
- let o = 0;
412
- for (const l of i)
413
- if (!l.hidden)
414
- if (l.children && l.children.length > 0) {
415
- const r = s(l.children, n + 1);
416
- r > 0 && (e[n - 1].push({
417
- column: l,
418
- colIndex: t,
419
- depth: n,
420
- colSpan: r,
421
- rowSpan: 1
422
- }), o += r);
423
- } else
424
- e[n - 1].push({
425
- column: l,
426
- colIndex: t++,
427
- depth: n,
428
- colSpan: 1,
429
- rowSpan: this._maxDepth - n + 1
430
- }), o++;
431
- return o;
432
- };
433
- return s(this._columns, 1), e;
434
- }
435
- /** 각 리프 컬럼의 계산된 너비 배열 반환 */
436
- computeWidths(e, t = 100) {
437
- const s = this.visibleLeaves, i = s.filter((r) => r.flex), n = s.filter((r) => !r.flex && r.width).reduce((r, a) => r + a.width, 0), o = i.reduce((r, a) => r + (a.flex ?? 1), 0), l = Math.max(0, e - n);
438
- return s.map((r) => r.flex ? Math.round(r.flex / o * l) : r.width ?? t);
439
- }
440
- }
441
- class Ze {
442
- constructor(e, t, s) {
443
- this._field = "", this._outsideHandler = null, this._onApply = t, this._onClear = s, this._el = document.createElement("div"), this._el.className = "og-filter-panel", this._el.style.cssText = `
444
- position:absolute;z-index:1000;min-width:200px;max-width:280px;
445
- background:var(--og-row-bg,#fff);border:1px solid var(--og-border-color,#e0e0e0);
446
- border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,0.15);
447
- padding:10px;box-sizing:border-box;display:none;font-size:13px;
448
- `, e.appendChild(this._el);
449
- }
450
- open(e, t, s) {
451
- var E;
452
- this._field = e, this._el.innerHTML = "";
453
- const i = document.createElement("div");
454
- i.textContent = "필터", i.style.cssText = "font-weight:600;margin-bottom:8px;color:var(--og-text-color,#333);", this._el.appendChild(i);
455
- const n = document.createElement("div");
456
- n.style.cssText = "display:flex;gap:4px;margin-bottom:6px;";
457
- const o = document.createElement("select");
458
- o.style.cssText = "flex:1;padding:3px 4px;border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;font-size:12px;";
459
- const l = [
460
- { label: "포함", value: "contains" },
461
- { label: "같음", value: "=" },
462
- { label: "같지 않음", value: "!=" },
463
- { label: "시작", value: "startsWith" },
464
- { label: "끝남", value: "endsWith" },
465
- { label: "보다 큼", value: ">" },
466
- { label: "보다 작음", value: "<" },
467
- { label: "이상", value: ">=" },
468
- { label: "이하", value: "<=" }
469
- ];
470
- for (const b of l) {
471
- const C = document.createElement("option");
472
- C.value = b.value, C.textContent = b.label, o.appendChild(C);
473
- }
474
- s[0] && (o.value = s[0].operator), n.appendChild(o), this._el.appendChild(n);
475
- const r = document.createElement("input");
476
- r.type = "text", r.placeholder = "필터 값 입력...", r.value = ((E = s[0]) == null ? void 0 : E.value) ?? "", r.style.cssText = `
477
- width:100%;padding:4px 6px;border:1px solid var(--og-border-color,#e0e0e0);
478
- border-radius:3px;font-size:12px;box-sizing:border-box;margin-bottom:8px;
479
- outline:none;
480
- `, r.addEventListener("keydown", (b) => {
481
- b.key === "Enter" ? h.click() : b.key === "Escape" && this.close();
482
- }), this._el.appendChild(r);
483
- const a = document.createElement("div");
484
- a.style.cssText = "display:flex;gap:6px;justify-content:flex-end;";
485
- const c = document.createElement("button");
486
- c.textContent = "초기화", c.style.cssText = `
487
- padding:3px 10px;border:1px solid var(--og-border-color,#e0e0e0);
488
- border-radius:3px;background:#fff;cursor:pointer;font-size:12px;color:#666;
489
- `, c.addEventListener("click", () => {
490
- this._onClear(this._field), this.close();
491
- });
492
- const h = document.createElement("button");
493
- h.textContent = "적용", h.style.cssText = `
494
- padding:3px 10px;border:1px solid var(--og-primary,#1976d2);
495
- border-radius:3px;background:var(--og-primary,#1976d2);
496
- color:#fff;cursor:pointer;font-size:12px;
497
- `, h.addEventListener("click", () => {
498
- const b = r.value.trim();
499
- b ? this._onApply(this._field, [{ operator: o.value, value: b }]) : this._onClear(this._field), this.close();
500
- }), a.appendChild(c), a.appendChild(h), this._el.appendChild(a);
501
- const u = t.getBoundingClientRect(), g = this._el.parentElement.getBoundingClientRect();
502
- this._el.style.top = `${u.bottom - g.top + 2}px`, this._el.style.left = `${Math.min(u.left - g.left, g.width - 220)}px`, this._el.style.display = "block", requestAnimationFrame(() => r.focus()), this._outsideHandler && document.removeEventListener("mousedown", this._outsideHandler), this._outsideHandler = (b) => {
503
- !this._el.contains(b.target) && b.target !== t && this.close();
504
- }, setTimeout(() => document.addEventListener("mousedown", this._outsideHandler), 0);
505
- }
506
- close() {
507
- this._el.style.display = "none", this._outsideHandler && (document.removeEventListener("mousedown", this._outsideHandler), this._outsideHandler = null);
508
- }
509
- get isOpen() {
510
- return this._el.style.display !== "none";
511
- }
512
- destroy() {
513
- this.close(), this._el.remove();
514
- }
515
- }
516
- const et = 10;
517
- function tt(d, e = et) {
518
- const t = Math.pow(10, e);
519
- return Math.round(d * t) / t;
520
- }
521
- class x {
522
- // scale = 소수점 아래 자릿수
523
- constructor(e, t) {
524
- this._c = e, this._s = t < 0 ? 0 : t;
525
- }
526
- // ── 생성 ─────────────────────────────────────────────────
527
- static from(e) {
528
- if (e instanceof x) return e;
529
- if (typeof e == "bigint") return new x(e, 0);
530
- const t = String(e).trim();
531
- if (!t || t === "null" || t === "undefined" || t === "NaN")
532
- return new x(0n, 0);
533
- const s = t.startsWith("-"), i = s ? t.slice(1) : t, n = i.indexOf(".");
534
- let o, l;
535
- if (n === -1)
536
- o = BigInt(i), l = 0;
537
- else {
538
- const r = i.slice(n + 1);
539
- o = BigInt(i.slice(0, n) + r), l = r.length;
540
- }
541
- return new x(s ? -o : o, l);
542
- }
543
- static zero() {
544
- return new x(0n, 0);
545
- }
546
- static one() {
547
- return new x(1n, 0);
548
- }
549
- // ── 내부: 두 값의 스케일 정렬 ────────────────────────────
550
- static _align(e, t) {
551
- return e._s === t._s ? [e._c, t._c, e._s] : e._s > t._s ? [e._c, t._c * 10n ** BigInt(e._s - t._s), e._s] : [e._c * 10n ** BigInt(t._s - e._s), t._c, t._s];
552
- }
553
- // ── 사칙연산 ─────────────────────────────────────────────
554
- add(e) {
555
- const [t, s, i] = x._align(this, x.from(e));
556
- return new x(t + s, i);
557
- }
558
- sub(e) {
559
- const [t, s, i] = x._align(this, x.from(e));
560
- return new x(t - s, i);
561
- }
562
- mul(e) {
563
- const t = x.from(e);
564
- return new x(this._c * t._c, this._s + t._s);
565
- }
566
- /**
567
- * 나눗셈. precision = 결과 소수점 자리수 (기본 20).
568
- * 수익 배분처럼 소수 수백 자리가 필요하면 precision을 높인다.
569
- */
570
- div(e, t = 20) {
571
- const s = x.from(e);
572
- if (s._c === 0n) throw new Error("OGDecimal: division by zero");
573
- const n = this._c * 10n ** BigInt(t + s._s) / s._c;
574
- return new x(n, t + this._s);
575
- }
576
- /** 나머지 (정수 나머지와 동일한 개념을 소수에 적용) */
577
- mod(e) {
578
- const t = x.from(e), [s, i, n] = x._align(this, t);
579
- return new x(s % i, n);
580
- }
581
- /** 부호 반전 */
582
- neg() {
583
- return new x(-this._c, this._s);
584
- }
585
- /** 절댓값 */
586
- abs() {
587
- return new x(this._c < 0n ? -this._c : this._c, this._s);
588
- }
589
- // ── 비교 ─────────────────────────────────────────────────
590
- eq(e) {
591
- const [t, s] = x._align(this, x.from(e));
592
- return t === s;
593
- }
594
- gt(e) {
595
- const [t, s] = x._align(this, x.from(e));
596
- return t > s;
597
- }
598
- lt(e) {
599
- const [t, s] = x._align(this, x.from(e));
600
- return t < s;
601
- }
602
- gte(e) {
603
- return !this.lt(e);
604
- }
605
- lte(e) {
606
- return !this.gt(e);
607
- }
608
- isZero() {
609
- return this._c === 0n;
610
- }
611
- isNeg() {
612
- return this._c < 0n;
613
- }
614
- isPos() {
615
- return this._c > 0n;
616
- }
617
- // ── 출력 ─────────────────────────────────────────────────
618
- /**
619
- * 지정 소수점 자리수로 반올림(Half-up) 후 문자열 반환.
620
- * 음원 배분 등 정확한 자리수 표시에 사용.
621
- */
622
- toFixed(e) {
623
- let t = this._c, s = this._s;
624
- if (s < e)
625
- t = t * 10n ** BigInt(e - s);
626
- else if (s > e) {
627
- const c = 10n ** BigInt(s - e), h = c / 2n, u = t < 0n, g = u ? -t : t, E = g % c;
628
- let b = g / c;
629
- E >= h && (b += 1n), t = u ? -b : b;
630
- }
631
- s = e;
632
- const i = t < 0n, o = (i ? -t : t).toString().padStart(e + 1, "0"), l = o.slice(0, o.length - e) || "0", r = e > 0 ? "." + o.slice(o.length - e) : "";
633
- return (i ? "-" : "") + l + r;
634
- }
635
- /** 정규화(후행 0 제거) 후 최소 표현 문자열 반환 */
636
- toString() {
637
- if (this._s === 0) return this._c.toString();
638
- let e = this._c, t = this._s;
639
- for (; t > 0 && e !== 0n && e % 10n === 0n; )
640
- e /= 10n, t--;
641
- return new x(e, t).toFixed(t);
642
- }
643
- /** number로 변환 (정밀도 손실 주의 — 표시 전용) */
644
- toNumber() {
645
- return parseFloat(this.toFixed(20));
646
- }
647
- // ── 집계 정적 메서드 ─────────────────────────────────────
648
- /** 정확한 합산 (내부적으로 BigInt 정수 연산) */
649
- static sum(e) {
650
- return e.reduce((t, s) => t.add(s), x.zero());
651
- }
652
- /** 정확한 평균. precision = 나눗셈 소수점 자리수 */
653
- static avg(e, t = 20) {
654
- return e.length ? x.sum(e).div(e.length, t) : x.zero();
655
- }
656
- /** 배열 최솟값 */
657
- static min(e) {
658
- if (!e.length) throw new Error("OGDecimal.min: empty array");
659
- return e.map(x.from).reduce((t, s) => t.lt(s) ? t : s);
660
- }
661
- /** 배열 최댓값 */
662
- static max(e) {
663
- if (!e.length) throw new Error("OGDecimal.max: empty array");
664
- return e.map(x.from).reduce((t, s) => t.gt(s) ? t : s);
665
- }
666
- }
667
- function Be(d, e, t = 30) {
668
- return new st(d, e, t).parse();
669
- }
670
- class st {
671
- constructor(e, t, s) {
672
- this._ctx = t, this._prec = s, this._pos = 0, this._src = e.trim();
673
- }
674
- parse() {
675
- const e = this._additive();
676
- if (this._skip(), this._pos < this._src.length)
677
- throw new SyntaxError(
678
- `FormulaEngine: 예상치 못한 토큰 '${this._src[this._pos]}' (위치 ${this._pos})`
679
- );
680
- return e;
681
- }
682
- // ── expression layers ──────────────────────────────────
683
- _additive() {
684
- let e = this._multiplicative();
685
- for (this._skip(); this._pos < this._src.length; ) {
686
- const t = this._src[this._pos];
687
- if (t !== "+" && t !== "-") break;
688
- this._pos++, this._skip();
689
- const s = this._multiplicative();
690
- e = t === "+" ? e.add(s) : e.sub(s), this._skip();
691
- }
692
- return e;
693
- }
694
- _multiplicative() {
695
- let e = this._unary();
696
- for (this._skip(); this._pos < this._src.length; ) {
697
- const t = this._src[this._pos];
698
- if (t !== "*" && t !== "/" && t !== "%") break;
699
- this._pos++, this._skip();
700
- const s = this._unary();
701
- t === "*" ? e = e.mul(s) : t === "/" ? e = e.div(s, this._prec) : e = e.mod(s), this._skip();
702
- }
703
- return e;
704
- }
705
- _unary() {
706
- return this._skip(), this._src[this._pos] === "-" ? (this._pos++, this._unary().neg()) : this._primary();
707
- }
708
- _primary() {
709
- this._skip();
710
- const e = this._src[this._pos];
711
- if (e === "(") {
712
- this._pos++;
713
- const t = this._additive();
714
- if (this._skip(), this._src[this._pos] !== ")")
715
- throw new SyntaxError("FormulaEngine: 닫는 괄호 ) 누락");
716
- return this._pos++, t;
717
- }
718
- return e === "[" ? this._fieldRef() : this._literal();
719
- }
720
- // ── 토큰 파싱 ─────────────────────────────────────────
721
- /** [fieldName] → 행 데이터에서 값 추출 */
722
- _fieldRef() {
723
- this._pos++;
724
- const e = this._pos;
725
- for (; this._pos < this._src.length && this._src[this._pos] !== "]"; )
726
- this._pos++;
727
- if (this._pos >= this._src.length)
728
- throw new SyntaxError("FormulaEngine: 닫는 ] 누락");
729
- const t = this._src.slice(e, this._pos);
730
- this._pos++;
731
- const s = this._ctx[t];
732
- if (s == null)
733
- throw new ReferenceError(`FormulaEngine: 필드 '[${t}]'가 행 데이터에 없습니다`);
734
- return x.from(s);
735
- }
736
- /** 숫자 리터럴 파싱 (정수 / 소수 모두) */
737
- _literal() {
738
- const e = this._pos;
739
- for (; this._pos < this._src.length && /[0-9.]/.test(this._src[this._pos]); )
740
- this._pos++;
741
- const t = this._src.slice(e, this._pos);
742
- if (!t)
743
- throw new SyntaxError(
744
- `FormulaEngine: 숫자 또는 [필드]를 기대했지만 '${this._src[this._pos] ?? "EOF"}' 발견 (위치 ${e})`
745
- );
746
- return x.from(t);
747
- }
748
- /** 공백 스킵 */
749
- _skip() {
750
- for (; this._pos < this._src.length && /\s/.test(this._src[this._pos]); )
751
- this._pos++;
752
- }
753
- }
754
- function ve(d, e) {
755
- if (d == null || d === "") return d ?? "";
756
- const t = typeof e == "string" ? { type: e } : e, s = t.char ?? "*";
757
- switch (t.type) {
758
- case "ssn":
759
- return it(d, s);
760
- case "phone":
761
- case "mobile":
762
- return nt(d, s);
763
- case "email":
764
- return ot(d, s);
765
- case "credit":
766
- return rt(d, s);
767
- case "account":
768
- return lt(d, s, t.visiblePrefix ?? 3, t.visibleSuffix ?? 4);
769
- case "password":
770
- return s.repeat(Math.max(d.length, 6));
771
- case "name":
772
- return at(d, s);
773
- case "ip":
774
- return dt(d, s);
775
- case "partial":
776
- return te(d, s, t.visiblePrefix ?? 0, t.visibleSuffix ?? 4);
777
- default:
778
- return d;
779
- }
780
- }
781
- function it(d, e) {
782
- const t = d.replace(/[^0-9]/g, "");
783
- if (t.length < 7) {
784
- const o = d.includes("-") ? "-" : "", l = d.indexOf("-") >= 0 ? d.indexOf("-") : 6;
785
- return d.slice(0, l) + o + e.repeat(Math.max(1, d.length - l - o.length));
786
- }
787
- const s = t.slice(0, 6), i = t[6], n = t.length - 7;
788
- return `${s}-${i}${e.repeat(n)}`;
789
- }
790
- function nt(d, e) {
791
- const t = d.replace(/[^0-9]/g, "");
792
- return t.length === 11 ? `${t.slice(0, 3)}-${e.repeat(4)}-${t.slice(7)}` : t.length === 10 ? t.startsWith("02") ? `${t.slice(0, 2)}-${e.repeat(4)}-${t.slice(6)}` : `${t.slice(0, 3)}-${e.repeat(3)}-${t.slice(6)}` : t.length === 9 ? `${t.slice(0, 2)}-${e.repeat(3)}-${t.slice(5)}` : te(d, e, 3, 4);
793
- }
794
- function ot(d, e) {
795
- const t = d.indexOf("@");
796
- if (t < 0) return te(d, e, 2, 0);
797
- const s = d.slice(0, t), i = d.slice(t), n = Math.min(2, s.length), o = s.slice(0, n), l = Math.max(s.length - n, 3);
798
- return `${o}${e.repeat(l)}${i}`;
799
- }
800
- function rt(d, e) {
801
- const t = d.replace(/[^0-9]/g, "");
802
- if (t.length < 8) return d;
803
- const s = t.slice(0, 4), i = t.slice(-4), n = t.length - 8, o = e.repeat(Math.max(n, 8)), l = [s];
804
- for (let r = 0; r < o.length; r += 4) {
805
- const a = o.slice(r, r + 4);
806
- a && l.push(a);
807
- }
808
- return l.push(i), l.join("-");
809
- }
810
- function lt(d, e, t, s) {
811
- const i = d.replace(/[^0-9]/g, "");
812
- if (i.length <= t + s)
813
- return te(i, e, t, s);
814
- const n = i.slice(0, t), o = i.slice(-s), l = i.length - t - s;
815
- return `${n}-${e.repeat(l)}-${o}`;
816
- }
817
- function at(d, e) {
818
- const t = d.trim();
819
- return t.length === 0 ? d : t.length === 1 ? e : t.length === 2 ? `${t[0]}${e}` : `${t[0]}${e.repeat(t.length - 2)}${t[t.length - 1]}`;
820
- }
821
- function dt(d, e) {
822
- const t = d.split(".");
823
- if (t.length !== 4) return te(d, e, 3, 0);
824
- const s = (i) => e.repeat(Math.max(i.length, 3));
825
- return `${t[0]}.${t[1]}.${s(t[2])}.${s(t[3])}`;
826
- }
827
- function te(d, e, t, s) {
828
- if (d.length <= t + s) return d;
829
- const i = d.slice(0, t), n = s > 0 ? d.slice(-s) : "", o = d.length - t - s;
830
- return `${i}${e.repeat(o)}${n}`;
831
- }
832
- function We(d) {
833
- const e = d.column;
834
- if (!e.formula) return null;
835
- const t = e.formulaPrecision ?? 30;
836
- try {
837
- let s;
838
- return typeof e.formula == "function" ? s = e.formula(d.row, x) : s = Be(e.formula, d.row, t), s instanceof x ? e.precision != null ? s.toFixed(e.precision) : s.toString() : typeof s == "string" ? s : e.precision != null ? x.from(s).toFixed(e.precision) : String(s);
839
- } catch (s) {
840
- return console.warn("[OpenGrid] Formula error:", s), "#ERR";
841
- }
842
- }
843
- function ct(d, e, t) {
844
- if (d == null || d === "") return "";
845
- let s = Number(d);
846
- if (isNaN(s)) return String(d);
847
- if (t != null && (s = tt(s, t)), !e)
848
- return t != null ? s.toFixed(t) : String(s);
849
- if (e.includes(",")) {
850
- const i = e.includes(".") ? e.split(".")[1].length : t ?? 0;
851
- return s.toLocaleString("ko-KR", {
852
- minimumFractionDigits: i,
853
- maximumFractionDigits: i
854
- });
855
- }
856
- return String(s);
857
- }
858
- function Ne(d, e = "yyyy-MM-dd") {
859
- if (!d) return "";
860
- const t = d instanceof Date ? d : new Date(d);
861
- if (isNaN(t.getTime())) return String(d);
862
- const s = t.getFullYear(), i = String(t.getMonth() + 1).padStart(2, "0"), n = String(t.getDate()).padStart(2, "0");
863
- return e.replace("yyyy", String(s)).replace("MM", i).replace("dd", n);
864
- }
865
- function ht(d, e, t) {
866
- const s = ve(d, e.mask), i = document.createElement("span");
867
- i.style.cssText = "display:flex;align-items:center;gap:3px;overflow:hidden;width:100%;box-sizing:border-box;";
868
- const n = document.createElement("span");
869
- n.style.cssText = "flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:monospace;letter-spacing:0.4px;color:var(--og-mask-text,#888);", n.textContent = s;
870
- const o = document.createElement("button");
871
- return o.title = "클릭하면 원문 표시", o.setAttribute("aria-label", "마스킹 해제"), o.innerHTML = '<svg width="13" height="13" viewBox="0 0 16 16" fill="currentColor"><path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8z"/><path d="M8 5.5A2.5 2.5 0 1 0 8 10.5 2.5 2.5 0 0 0 8 5.5zm0 4A1.5 1.5 0 1 1 8 6.5a1.5 1.5 0 0 1 0 3z" fill="#fff"/></svg>', o.style.cssText = "flex-shrink:0;background:none;border:none;cursor:pointer;color:#c0c0c0;padding:1px 2px;line-height:0;border-radius:3px;display:flex;align-items:center;", o.addEventListener("mouseover", () => {
872
- o.style.color = "var(--og-primary,#1976d2)", o.style.background = "rgba(25,118,210,0.08)";
873
- }), o.addEventListener("mouseout", () => {
874
- o.style.color = "#c0c0c0", o.style.background = "none";
875
- }), o.addEventListener("click", (l) => {
876
- l.stopPropagation(), n.textContent = d, n.style.fontFamily = "", n.style.letterSpacing = "", n.style.color = "", o.remove(), (e._maskRevealedRows ?? (e._maskRevealedRows = /* @__PURE__ */ new Set())).add(t);
877
- }), i.appendChild(n), i.appendChild(o), i;
878
- }
879
- class ae {
880
- render(e) {
881
- var r;
882
- const t = document.createElement("span");
883
- t.className = "og-cell-text";
884
- const s = We(e);
885
- if (s !== null)
886
- return t.textContent = s, t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;", t;
887
- const { value: i, column: n, rowIndex: o } = e;
888
- let l;
889
- if (n.valueMap && i != null && n.valueMap[i] ? l = n.valueMap[i] : l = i == null ? "" : String(i), n.mask) {
890
- const a = n._maskRevealed === !0, c = ((r = n._maskRevealedRows) == null ? void 0 : r.has(o)) === !0;
891
- if (!a && !c)
892
- return ht(l, n, o);
893
- }
894
- return t.textContent = l, t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;", t;
895
- }
896
- }
897
- class ut {
898
- constructor(e = [], t) {
899
- this._opts = e.map(
900
- (s) => typeof s == "string" ? { label: s, value: s } : { label: s.label ?? s.text ?? String(s.value ?? ""), value: s.value }
901
- ), this._fn = t ?? null;
902
- }
903
- render(e) {
904
- const t = document.createElement("span");
905
- t.className = "og-cell-text", t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;";
906
- const s = e.value;
907
- if (s == null || s === "") return t;
908
- const i = String(s), o = (this._fn ? this._fn(e.row, e.rowIndex).map((l) => typeof l == "string" ? { label: l, value: l } : { label: l.label ?? l.text ?? String(l.value ?? ""), value: l.value }) : this._opts).find((l) => String(l.value) === i);
909
- return t.textContent = o ? o.label : i, t;
910
- }
911
- }
912
- class de {
913
- render(e) {
914
- const t = document.createElement("span");
915
- t.className = "og-cell-number";
916
- const s = We(e);
917
- return s !== null ? (t.textContent = s, t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;text-align:right;", t) : (t.textContent = ct(e.value, e.column.format ?? "#,##0", e.column.precision), t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;text-align:right;", t);
918
- }
919
- }
920
- class ce {
921
- render(e) {
922
- const t = document.createElement("span");
923
- return t.className = "og-cell-date", t.textContent = Ne(e.value, e.column.format), t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;", t;
924
- }
925
- }
926
- class he {
927
- render(e) {
928
- const t = document.createElement("span");
929
- t.className = "og-cell-checkbox", t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;";
930
- const s = document.createElement("input");
931
- return s.type = "checkbox", s.checked = !!e.value, s.disabled = !0, s.style.cssText += "cursor:pointer;pointer-events:none;", t.appendChild(s), t;
932
- }
933
- }
934
- class Re {
935
- constructor(e) {
936
- this.def = e;
937
- }
938
- render(e) {
939
- var n, o, l;
940
- const t = document.createElement("span");
941
- t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;";
942
- const s = document.createElement("button");
943
- s.className = `og-cell-btn${(n = this.def) != null && n.buttonClass ? " " + this.def.buttonClass : ""}`;
944
- const i = (o = this.def) == null ? void 0 : o.label;
945
- return typeof i == "function" ? s.textContent = i(e.value, e.row) : s.textContent = i ?? String(e.value ?? "btn"), s.style.cssText = `
946
- padding:2px 10px;border:1px solid var(--og-primary,#1976d2);
947
- border-radius:4px;background:var(--og-row-bg,#fff);color:var(--og-primary,#1976d2);
948
- cursor:pointer;font-size:12px;white-space:nowrap;transition:background 0.12s;
949
- ${((l = this.def) == null ? void 0 : l.style) ?? ""}
950
- `, s.addEventListener("mouseover", () => s.style.background = "var(--og-primary-light,#e3f2fd)"), s.addEventListener("mouseout", () => s.style.background = "var(--og-row-bg,#fff)"), t.appendChild(s), t;
951
- }
952
- }
953
- class ke {
954
- constructor(e, t) {
955
- this.colorMap = e, this.labelMap = t;
956
- }
957
- render(e) {
958
- var l, r, a;
959
- const t = document.createElement("span");
960
- t.style.cssText = "display:flex;align-items:center;height:100%;";
961
- const s = document.createElement("span"), i = e.value == null ? "" : String(e.value), n = ((l = this.labelMap) == null ? void 0 : l[i]) ?? ((r = e.column.valueMap) == null ? void 0 : r[i]) ?? i;
962
- s.textContent = n;
963
- const o = ((a = this.colorMap) == null ? void 0 : a[i]) ?? "#666";
964
- return s.style.cssText = `
965
- display:inline-block;padding:2px 8px;border-radius:12px;font-size:11px;
966
- background:${o}22;color:${o};border:1px solid ${o}66;
967
- white-space:nowrap;
968
- `, t.appendChild(s), t;
969
- }
970
- }
971
- class Ee {
972
- constructor(e, t) {
973
- this.hrefFn = e, this.target = t;
974
- }
975
- render(e) {
976
- const t = document.createElement("a");
977
- return t.className = "og-cell-link", t.textContent = e.value == null ? "" : String(e.value), t.href = this.hrefFn ? this.hrefFn(e.value, e.row) : "#", this.target && (t.target = this.target), t.style.cssText = "color:var(--og-primary,#1976d2);text-decoration:underline;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;", this.hrefFn || t.addEventListener("click", (s) => s.preventDefault()), t;
978
- }
979
- }
980
- class gt {
981
- constructor(e) {
982
- this.templateFn = e;
983
- }
984
- render(e) {
985
- const t = document.createElement("div");
986
- return t.className = "og-cell-template", t.style.cssText = "display:flex;align-items:center;height:100%;overflow:hidden;", t.innerHTML = this.templateFn(e.value, e.row, e.rowIndex), t;
987
- }
988
- }
989
- class pt {
990
- constructor(e) {
991
- this.def = e;
992
- }
993
- render(e) {
994
- var a, c, h, u, g;
995
- const t = document.createElement("span");
996
- t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;";
997
- const s = document.createElement("img"), i = (a = this.def) != null && a.srcFn ? this.def.srcFn(e.value, e.row) : String(e.value ?? "");
998
- s.src = i;
999
- const n = ((c = this.def) == null ? void 0 : c.width) ?? 28, o = ((h = this.def) == null ? void 0 : h.height) ?? 28, l = ((u = this.def) == null ? void 0 : u.radius) ?? 4;
1000
- s.style.cssText = `width:${n}px;height:${o}px;object-fit:cover;border-radius:${l}px;display:block;`;
1001
- const r = (g = this.def) == null ? void 0 : g.alt;
1002
- return s.alt = typeof r == "function" ? r(e.value, e.row) : r ?? "", s.onerror = () => {
1003
- s.style.display = "none";
1004
- }, t.appendChild(s), t;
1005
- }
1006
- }
1007
- class _t {
1008
- constructor(e) {
1009
- this.def = e;
1010
- }
1011
- render(e) {
1012
- var a, c, h, u;
1013
- const t = document.createElement("span");
1014
- t.style.cssText = "display:flex;align-items:center;gap:5px;width:100%;padding:0 4px;box-sizing:border-box;";
1015
- const s = ((a = this.def) == null ? void 0 : a.max) ?? 100, i = Number(e.value) || 0, n = Math.min(100, Math.max(0, i / s * 100)), o = (c = this.def) != null && c.colorFn ? this.def.colorFn(i) : ((h = this.def) == null ? void 0 : h.color) ?? "var(--og-primary,#1976d2)", l = document.createElement("div");
1016
- l.className = "og-progress-track", l.style.cssText = "flex:1;height:10px;background:#e0e0e0;border-radius:5px;overflow:hidden;";
1017
- const r = document.createElement("div");
1018
- if (r.className = "og-progress-fill", r.style.cssText = `width:${n}%;height:100%;background:${o};border-radius:5px;`, l.appendChild(r), t.appendChild(l), ((u = this.def) == null ? void 0 : u.showLabel) !== !1) {
1019
- const g = document.createElement("span");
1020
- g.style.cssText = "font-size:11px;color:#666;white-space:nowrap;min-width:28px;text-align:right;", g.textContent = `${Math.round(n)}%`, t.appendChild(g);
1021
- }
1022
- return t;
1023
- }
1024
- }
1025
- class ft {
1026
- constructor(e) {
1027
- this.def = e;
1028
- }
1029
- render(e) {
1030
- var c, h, u, g;
1031
- const t = document.createElement("span");
1032
- t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;";
1033
- const s = Array.isArray(e.value) ? e.value.map(Number) : [];
1034
- if (!s.length)
1035
- return t.textContent = "-", t;
1036
- const i = ((c = this.def) == null ? void 0 : c.width) ?? 80, n = ((h = this.def) == null ? void 0 : h.height) ?? 22, o = ((u = this.def) == null ? void 0 : u.color) ?? "#1976d2", l = ((g = this.def) == null ? void 0 : g.chartType) ?? "bar", r = document.createElement("canvas");
1037
- r.width = i, r.height = n, r.style.cssText = "display:block;";
1038
- const a = r.getContext("2d");
1039
- if (a) {
1040
- const E = Math.max(...s, 1), b = Math.min(...s, 0), C = E - b || 1, M = s.length;
1041
- if (l === "bar") {
1042
- const _ = i / M;
1043
- s.forEach((y, p) => {
1044
- const A = (y - b) / C * (n - 2);
1045
- a.fillStyle = o, a.fillRect(p * _ + 1, n - A - 1, _ - 2, A);
1046
- });
1047
- } else {
1048
- const _ = s.map((y, p) => ({
1049
- x: p / (M - 1 || 1) * i,
1050
- y: n - (y - b) / C * (n - 4) - 2
1051
- }));
1052
- l === "area" && (a.fillStyle = o + "33", a.beginPath(), a.moveTo(_[0].x, n), _.forEach((y) => a.lineTo(y.x, y.y)), a.lineTo(_[_.length - 1].x, n), a.closePath(), a.fill()), a.strokeStyle = o, a.lineWidth = 1.5, a.beginPath(), _.forEach((y, p) => p === 0 ? a.moveTo(y.x, y.y) : a.lineTo(y.x, y.y)), a.stroke();
1053
- }
1054
- }
1055
- return t.appendChild(r), t;
1056
- }
1057
- }
1058
- class Se {
1059
- render(e) {
1060
- const t = document.createElement("span");
1061
- t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;";
1062
- const s = !!e.value, i = document.createElement("span");
1063
- i.className = "og-switch" + (s ? " og-switch--on" : ""), i.style.cssText = `display:inline-block;width:34px;height:18px;border-radius:9px;
1064
- background:${s ? "var(--og-primary,#1976d2)" : "#bdbdbd"};
1065
- position:relative;transition:background 0.2s;cursor:pointer;flex-shrink:0;pointer-events:none;`;
1066
- const n = document.createElement("span");
1067
- return n.style.cssText = `position:absolute;top:2px;left:${s ? "16px" : "2px"};
1068
- width:14px;height:14px;border-radius:50%;background:#fff;
1069
- transition:left 0.2s;box-shadow:0 1px 3px rgba(0,0,0,0.3);`, i.appendChild(n), t.appendChild(i), t;
1070
- }
1071
- }
1072
- class mt {
1073
- constructor(e) {
1074
- this.def = e;
1075
- }
1076
- render(e) {
1077
- var o, l;
1078
- const t = document.createElement("span");
1079
- t.style.cssText = "display:flex;align-items:center;gap:1px;height:100%;";
1080
- const s = ((o = this.def) == null ? void 0 : o.max) ?? 5, i = Math.round(Number(e.value) || 0), n = ((l = this.def) == null ? void 0 : l.color) ?? "#ffa000";
1081
- for (let r = 1; r <= s; r++) {
1082
- const a = document.createElement("span");
1083
- a.textContent = "★", a.style.cssText = `font-size:14px;color:${r <= i ? n : "#e0e0e0"};line-height:1;`, t.appendChild(a);
1084
- }
1085
- return t;
1086
- }
1087
- }
1088
- class ue {
1089
- render(e) {
1090
- const t = document.createElement("span");
1091
- t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;pointer-events:none;";
1092
- const s = document.createElement("input");
1093
- return s.type = "radio", s.checked = !!e.value, s.setAttribute("aria-checked", e.value ? "true" : "false"), s.setAttribute("aria-label", e.column.header ?? "선택"), e.column.group && (s.name = `og-radio-${e.rowIndex}-${e.column.group}`), s.style.cssText = "width:14px;height:14px;cursor:pointer;accent-color:var(--og-primary,#1976d2);", t.appendChild(s), t;
1094
- }
1095
- }
1096
- class ge {
1097
- render(e) {
1098
- const t = document.createElement("span");
1099
- if (t.style.cssText = "display:flex;align-items:center;justify-content:center;height:100%;overflow:hidden;", !e.value) return t;
1100
- const s = document.createElement("img");
1101
- return s.src = String(e.value), s.alt = e.column.alt ?? e.column.field, s.style.cssText = "max-width:100%;max-height:100%;object-fit:contain;display:block;", s.setAttribute("role", "img"), t.appendChild(s), t;
1102
- }
1103
- }
1104
- function bt(d) {
1105
- const e = document.createElement("div");
1106
- return e.innerHTML = d, e.querySelectorAll("script,iframe,object,embed").forEach((t) => t.remove()), e.querySelectorAll("*").forEach((t) => {
1107
- for (const s of [...t.attributes])
1108
- s.name.startsWith("on") && t.removeAttribute(s.name);
1109
- if (t.tagName === "A") {
1110
- const s = t.getAttribute("href") ?? "";
1111
- /^javascript:/i.test(s) && t.removeAttribute("href");
1112
- }
1113
- }), e.innerHTML;
1114
- }
1115
- class pe {
1116
- render(e) {
1117
- const t = document.createElement("span");
1118
- t.style.cssText = "display:block;overflow:hidden;width:100%;";
1119
- const s = e.column.sanitize !== !1, i = String(e.value ?? "");
1120
- return t.innerHTML = s ? bt(i) : i, t;
1121
- }
1122
- }
1123
- const wt = [
1124
- "212222",
1125
- "222122",
1126
- "222221",
1127
- "121223",
1128
- "121322",
1129
- "131222",
1130
- "122213",
1131
- "122312",
1132
- // 0-7
1133
- "132212",
1134
- "221213",
1135
- "221312",
1136
- "231212",
1137
- "112232",
1138
- "122132",
1139
- "122231",
1140
- "113222",
1141
- // 8-15
1142
- "123122",
1143
- "123221",
1144
- "223211",
1145
- "221132",
1146
- "221231",
1147
- "213212",
1148
- "223112",
1149
- "312131",
1150
- // 16-23
1151
- "311222",
1152
- "321122",
1153
- "321221",
1154
- "312212",
1155
- "322112",
1156
- "322211",
1157
- "212123",
1158
- "212321",
1159
- // 24-31
1160
- "232121",
1161
- "111323",
1162
- "131123",
1163
- "131321",
1164
- "112313",
1165
- "132113",
1166
- "132311",
1167
- "211313",
1168
- // 32-39
1169
- "231113",
1170
- "231311",
1171
- "112133",
1172
- "112331",
1173
- "132131",
1174
- "113123",
1175
- "113321",
1176
- "133121",
1177
- // 40-47
1178
- "313121",
1179
- "211331",
1180
- "231131",
1181
- "213113",
1182
- "213311",
1183
- "213131",
1184
- "311123",
1185
- "311321",
1186
- // 48-55
1187
- "331121",
1188
- "312113",
1189
- "312311",
1190
- "332111",
1191
- "314111",
1192
- "221411",
1193
- "431111",
1194
- "111224",
1195
- // 56-63
1196
- "111422",
1197
- "121124",
1198
- "121421",
1199
- "141122",
1200
- "141221",
1201
- "112214",
1202
- "112412",
1203
- "122114",
1204
- // 64-71
1205
- "122411",
1206
- "142112",
1207
- "142211",
1208
- "241211",
1209
- "221114",
1210
- "413111",
1211
- "241112",
1212
- "134111",
1213
- // 72-79
1214
- "111242",
1215
- "121142",
1216
- "121241",
1217
- "114212",
1218
- "124112",
1219
- "124211",
1220
- "411212",
1221
- "421112",
1222
- // 80-87
1223
- "421211",
1224
- "212141",
1225
- "214121",
1226
- "412121",
1227
- "111143",
1228
- "111341",
1229
- "131141",
1230
- "114113",
1231
- // 88-95
1232
- "114311",
1233
- "411113",
1234
- "411311",
1235
- "113141",
1236
- "114131",
1237
- "311141",
1238
- "411131",
1239
- "211412",
1240
- // 96-103
1241
- "211214",
1242
- "211232"
1243
- // 104 (Start B), 105 (Start C)
1244
- ], yt = "2331112";
1245
- function Le(d) {
1246
- let e = "", t = !0;
1247
- for (const s of d)
1248
- e += (t ? "1" : "0").repeat(+s), t = !t;
1249
- return e;
1250
- }
1251
- function vt(d) {
1252
- const e = [104];
1253
- for (const s of d) {
1254
- const i = s.charCodeAt(0) - 32;
1255
- i >= 0 && i <= 94 && e.push(i);
1256
- }
1257
- let t = 104;
1258
- for (let s = 1; s < e.length; s++) t += e[s] * s;
1259
- return e.push(t % 103), e.map((s) => Le(wt[s])).join("") + Le(yt) + "11";
1260
- }
1261
- class _e {
1262
- render(e) {
1263
- const t = String(e.value ?? ""), s = e.column.barcodeHeight ?? 28, i = document.createElement("div");
1264
- i.style.cssText = "display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;overflow:hidden;gap:1px;", i.setAttribute("role", "img"), i.setAttribute("aria-label", `바코드: ${t}`), i.innerHTML = xt(t, s);
1265
- const n = document.createElement("span");
1266
- return n.textContent = t, n.style.cssText = "font-size:9px;font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;", i.appendChild(n), i;
1267
- }
1268
- }
1269
- function xt(d, e) {
1270
- if (!d) return "";
1271
- const t = vt(d), s = 1.4, i = 6, n = t.length * s + i * 2, o = [];
1272
- let l = 0, r = i;
1273
- for (; l < t.length; )
1274
- if (t[l] === "1") {
1275
- let a = 0;
1276
- for (; l + a < t.length && t[l + a] === "1"; ) a++;
1277
- o.push(`<rect x="${r.toFixed(2)}" y="0" width="${(a * s).toFixed(2)}" height="${e}"/>`), r += a * s, l += a;
1278
- } else
1279
- r += s, l++;
1280
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${n.toFixed(2)} ${e}" width="${n.toFixed(2)}" height="${e}" style="display:block" aria-hidden="true"><g fill="currentColor">${o.join("")}</g></svg>`;
1281
- }
1282
- function Ct(d) {
1283
- const e = d.renderer;
1284
- if (!e)
1285
- switch (d.type) {
1286
- case "number":
1287
- return new de();
1288
- case "date":
1289
- return new ce();
1290
- case "boolean":
1291
- return new he();
1292
- case "radio":
1293
- return new ue();
1294
- case "img":
1295
- return new ge();
1296
- case "html":
1297
- return new pe();
1298
- case "barcode":
1299
- return new _e();
1300
- case "select":
1301
- return new ut(d.options ?? [], d.optionsFn);
1302
- default:
1303
- return new ae();
1304
- }
1305
- if (typeof e == "string")
1306
- switch (e) {
1307
- case "number":
1308
- return new de();
1309
- case "date":
1310
- return new ce();
1311
- case "checkbox":
1312
- return new he();
1313
- case "button":
1314
- return new Re();
1315
- case "link":
1316
- return new Ee();
1317
- case "badge":
1318
- return new ke();
1319
- case "switch":
1320
- return new Se();
1321
- case "radio":
1322
- return new ue();
1323
- case "img":
1324
- return new ge();
1325
- case "html":
1326
- return new pe();
1327
- case "barcode":
1328
- return new _e();
1329
- default:
1330
- return new ae();
1331
- }
1332
- switch (e.type) {
1333
- case "button":
1334
- return new Re(e);
1335
- case "checkbox":
1336
- return new he();
1337
- case "link":
1338
- return new Ee(e.hrefFn, e.target);
1339
- case "template":
1340
- return new gt(e.templateFn);
1341
- case "badge":
1342
- return new ke(e.colorMap, e.labelMap ?? e.valueMap);
1343
- case "image":
1344
- return new pt(e);
1345
- case "progress":
1346
- return new _t(e);
1347
- case "sparkline":
1348
- return new ft(e);
1349
- case "switch":
1350
- return new Se();
1351
- case "rating":
1352
- return new mt(e);
1353
- case "number":
1354
- return new de();
1355
- case "date":
1356
- return new ce();
1357
- case "radio":
1358
- return new ue();
1359
- case "img":
1360
- return new ge();
1361
- case "html":
1362
- return new pe();
1363
- case "barcode":
1364
- return new _e();
1365
- default:
1366
- return new ae();
1367
- }
1368
- }
1369
- class Mt {
1370
- constructor(e, t, s) {
1371
- this._cellMap = /* @__PURE__ */ new Map(), this._root = e, this._opts = t, this._cbs = s, this._header = L("div", "og-header"), this._header.style.cssText = "flex-shrink:0;overflow-x:auto;overflow-y:hidden;border:0;border-bottom:1px solid var(--og-border-color,#e0e0e0);scrollbar-width:none;", this._bodyWrap = L("div", "og-body-wrapper"), this._bodyWrap.style.cssText = "flex:1;overflow:auto;position:relative;", this._bodyWrap.style.setProperty("--scrollbar-size", "8px"), this._body = L("div", "og-body"), this._body.style.cssText = "position:relative;", this._bodyWrap.appendChild(this._body), e.appendChild(this._header), e.appendChild(this._bodyWrap), this._bodyWrap.addEventListener("scroll", () => {
1372
- this._header.scrollLeft = this._bodyWrap.scrollLeft;
1373
- }, { passive: !0 });
1374
- }
1375
- get bodyWrapper() {
1376
- return this._bodyWrap;
1377
- }
1378
- updateSize(e, t) {
1379
- this._bodyWrap.style.height = `${e - t}px`;
1380
- }
1381
- renderHeader(e, t, s, i, n) {
1382
- var g, E;
1383
- this._header.innerHTML = "";
1384
- const o = n._frozenCount ?? 0;
1385
- let l = 0;
1386
- n.stateColumn && (l += 24), n.draggable && (l += 18), n.rowNumber && (l += 44), n.checkColumn && (l += 36);
1387
- const r = l + t.reduce((b, C, M) => b + (s[M] ?? n.defaultColumnWidth), 0);
1388
- this._header.style.background = "var(--og-header-bg,#f5f5f5)";
1389
- const a = L("table", "og-header-table");
1390
- a.setAttribute("role", "presentation"), a.style.cssText = `table-layout:fixed;border-collapse:collapse;border-spacing:0;margin:0;width:${r}px;background:var(--og-header-bg,#f5f5f5);`;
1391
- const c = e.length;
1392
- let h = 0;
1393
- const u = (b, C, M, _ = "") => {
1394
- const y = L("th", `og-header-cell og-extra-col ${_}`);
1395
- y.setAttribute("rowspan", String(c)), y.textContent = M, Te(y, {
1396
- width: `${C}px`,
1397
- minWidth: `${C}px`,
1398
- textAlign: "center",
1399
- borderRight: "1px solid var(--og-border-color,#e0e0e0)",
1400
- borderBottom: "1px solid var(--og-border-color,#e0e0e0)",
1401
- // host isolation: extra 컬럼 th 도 호스트 th{} 침범 차단 (border/line-height)
1402
- borderTop: "0",
1403
- borderLeft: "0",
1404
- lineHeight: "normal",
1405
- verticalAlign: "middle",
1406
- padding: "0",
1407
- fontSize: "11px",
1408
- color: "#999",
1409
- userSelect: "none",
1410
- boxSizing: "border-box",
1411
- background: "var(--og-header-bg,#f5f5f5)"
1412
- }), o > 0 && (y.style.position = "sticky", y.style.left = `${h}px`, y.style.zIndex = "4"), h += C, b.appendChild(y);
1413
- };
1414
- for (let b = 0; b < e.length; b++) {
1415
- const C = L("tr", "og-header-row");
1416
- if (C.style.height = `${n.headerHeight}px`, b === 0 && (n.stateColumn && u(C, 24, ""), n.draggable && u(C, 18, ""), n.rowNumber && u(C, 44, "No"), n.checkColumn)) {
1417
- const M = L("th", "og-header-cell og-extra-col");
1418
- M.setAttribute("rowspan", String(c)), M.style.cssText = "width:36px;min-width:36px;text-align:center;border-right:1px solid var(--og-border-color,#e0e0e0);border-bottom:1px solid var(--og-border-color,#e0e0e0);border-top:0;border-left:0;line-height:normal;vertical-align:middle;background:var(--og-header-bg,#f5f5f5);box-sizing:border-box;", o > 0 && (M.style.position = "sticky", M.style.left = `${h}px`, M.style.zIndex = "4"), h += 36;
1419
- const _ = document.createElement("input");
1420
- _.type = "checkbox", _.setAttribute("aria-label", "전체 행 선택"), _.style.cssText = "width:16px;height:16px;", _.addEventListener("change", () => this._cbs.onAllCheck(_.checked)), M.appendChild(_), C.appendChild(M);
1421
- }
1422
- for (const M of e[b] ?? []) {
1423
- const _ = L("th", "og-header-cell"), y = M.column;
1424
- M.colSpan > 1 && (_.colSpan = M.colSpan), M.rowSpan > 1 && (_.rowSpan = M.rowSpan);
1425
- const p = M.colSpan === 1 ? t.findIndex((m) => m.field === y.field) : -1;
1426
- if (M.colSpan === 1) {
1427
- const m = p >= 0 ? s[p] ?? n.defaultColumnWidth : y.width ?? n.defaultColumnWidth;
1428
- _.style.width = `${m}px`, _.style.minWidth = `${m}px`;
1429
- }
1430
- const A = i.find((m) => m.field === y.field), T = y.sortable !== !1 && n.sortable && M.colSpan === 1;
1431
- if (_.setAttribute("role", "columnheader"), _.setAttribute("scope", "col"), T && (_.setAttribute("aria-sort", A ? A.dir === "asc" ? "ascending" : "descending" : "none"), _.tabIndex = p === 0 ? 0 : -1, _.addEventListener("keydown", (m) => {
1432
- if (m.key === "Enter" || m.key === " ")
1433
- m.preventDefault(), this._cbs.onHeaderClick(y.field, m.shiftKey);
1434
- else if (m.key === "ArrowRight") {
1435
- m.preventDefault();
1436
- const v = _.nextElementSibling;
1437
- (v == null ? void 0 : v.tagName) === "TH" && v.focus();
1438
- } else if (m.key === "ArrowLeft") {
1439
- m.preventDefault();
1440
- const v = _.previousElementSibling;
1441
- (v == null ? void 0 : v.tagName) === "TH" && v.focus();
1442
- }
1443
- })), p >= 0 && p < o) {
1444
- let m = 0;
1445
- n.stateColumn && (m += 24), n.draggable && (m += 18), n.rowNumber && (m += 44), n.checkColumn && (m += 36);
1446
- for (let v = 0; v < p; v++) m += s[v] ?? n.defaultColumnWidth;
1447
- _.classList.add("og-frozen"), p === o - 1 && _.classList.add("og-frozen-last"), _.style.left = `${m}px`;
1448
- }
1449
- Te(_, {
1450
- padding: "4px 8px",
1451
- boxSizing: "border-box",
1452
- // host isolation: 헤더 <th> 의 모든 시각 속성을 인라인으로 고정한다.
1453
- // 임베드 호스트(WordPress 등)가 `.entry-content th`/`.fn-post-content th`(특이도 0,2,1)로
1454
- // 배경·글자·라인높이·보더·폰트크기를 덮어써도 인라인(최고 우선순위)이 이긴다.
1455
- // (var 참조라 setTheme 시 자동 반영. text-align/padding 은 그리드 의도값 유지)
1456
- background: "var(--og-header-bg)",
1457
- color: "var(--og-header-color)",
1458
- lineHeight: "normal",
1459
- verticalAlign: "middle",
1460
- fontSize: "var(--og-font-size)",
1461
- textAlign: y.headerAlign ?? "center",
1462
- borderTop: "0",
1463
- borderLeft: "0",
1464
- borderRight: "1px solid var(--og-border-color,#e0e0e0)",
1465
- borderBottom: "1px solid var(--og-border-color,#e0e0e0)",
1466
- userSelect: "none",
1467
- cursor: T ? "pointer" : "default",
1468
- whiteSpace: "nowrap",
1469
- overflow: "hidden",
1470
- textOverflow: "ellipsis",
1471
- position: "relative"
1472
- }), _.title = (typeof y.tooltip == "string" ? y.tooltip : y.header ?? y.field) ?? "";
1473
- const F = L("span");
1474
- if (F.textContent = y.header ?? y.field, F.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;", _.appendChild(F), A) {
1475
- _.classList.add("og-sorted");
1476
- const m = L("span", "og-sort-icon");
1477
- m.textContent = A.dir === "asc" ? " ↑" : " ↓", _.appendChild(m);
1478
- }
1479
- if (y.filterable !== !1 && n.filterable && M.colSpan === 1) {
1480
- const m = L("span", "og-filter-icon"), v = ((E = (g = n._activeFilters) == null ? void 0 : g[y.field]) == null ? void 0 : E.length) > 0;
1481
- m.textContent = v ? "⊿" : "▿", m.title = "필터", m.style.cssText = "margin-left:3px;cursor:pointer;font-size:10px;opacity:0.6;", v && m.classList.add("og-filter-icon--active"), m.addEventListener("click", (k) => {
1482
- k.stopPropagation(), this._cbs.onFilterIconClick(y.field, m);
1483
- }), _.appendChild(m);
1484
- }
1485
- if (y.resizable !== !1) {
1486
- const m = L("div", "og-resize-handle");
1487
- m.style.cssText = "position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1;", _.appendChild(m);
1488
- const v = p;
1489
- Rt(m, _, (k) => {
1490
- v >= 0 && this._cbs.onColResize(v, k);
1491
- });
1492
- }
1493
- n.columnReorder && p >= 0 && M.colSpan === 1 && (_.draggable = !0, _.addEventListener("dragstart", (m) => {
1494
- var v;
1495
- this._cbs.onColDragStart(p), _.classList.add("og-col-dragging"), (v = m.dataTransfer) == null || v.setData("text/plain", String(p));
1496
- }), _.addEventListener("dragend", () => {
1497
- _.classList.remove("og-col-dragging"), this._header.querySelectorAll(".og-col-drop-over").forEach((m) => m.classList.remove("og-col-drop-over"));
1498
- }), _.addEventListener("dragover", (m) => {
1499
- m.preventDefault();
1500
- const v = this._cbs.getColDragIdx();
1501
- v !== null && v !== p && (this._header.querySelectorAll(".og-col-drop-over").forEach((k) => k.classList.remove("og-col-drop-over")), _.classList.add("og-col-drop-over"));
1502
- }), _.addEventListener("dragleave", () => {
1503
- _.classList.remove("og-col-drop-over");
1504
- }), _.addEventListener("drop", (m) => {
1505
- m.preventDefault(), _.classList.remove("og-col-drop-over"), this._cbs.onColDrop(p);
1506
- })), T && _.addEventListener("click", (m) => {
1507
- m.target.classList.contains("og-resize-handle") || this._cbs.onHeaderClick(y.field, m.shiftKey);
1508
- }), C.appendChild(_);
1509
- }
1510
- a.appendChild(C);
1511
- }
1512
- this._header.appendChild(a);
1513
- }
1514
- renderBody(e, t, s, i, n, o, l, r, a, c, h = null, u, g, E = {}, b) {
1515
- var _, y;
1516
- Object.keys(E).length && (o = { ...o, ...E }), this._body.innerHTML = "", this._cellMap.clear(), this._body.style.height = `${r}px`;
1517
- const C = o._frozenCount ?? 0;
1518
- {
1519
- let p = 0;
1520
- o.stateColumn && (p += 24), o.draggable && (p += 18), o.rowNumber && (p += 44), o.checkColumn && (p += 36);
1521
- const A = p + i.reduce((T, F, z) => T + (n[z] ?? o.defaultColumnWidth), 0);
1522
- this._body.style.minWidth = `${A}px`;
1523
- }
1524
- if (t < e) return;
1525
- const M = document.createDocumentFragment();
1526
- for (let p = e; p <= t; p++) {
1527
- const A = h ? h[p] : null, T = A && A._isGroup === !0, F = A && A._isTree === !0;
1528
- if (T) {
1529
- const f = A, S = `__${f._groupField}:${f._groupValue}`, $ = L("div", "og-group-row"), se = l + (p - e) * o.rowHeight;
1530
- $.style.cssText = [
1531
- `top:${se}px;height:${o.rowHeight}px;`,
1532
- "display:flex;align-items:stretch;cursor:pointer;",
1533
- `padding-left:${4 + f._depth * 12}px;`,
1534
- "background:var(--og-header-bg,#f5f5f5);",
1535
- // host isolation: border:0 선행 (WP :where([style*=border-color]) 의 3px 강제 차단)
1536
- "border:0;border-bottom:1px solid var(--og-border-color,#e0e0e0);"
1537
- ].join(""), $.setAttribute("role", "row"), $.setAttribute("aria-expanded", f._expanded ? "true" : "false"), $.setAttribute("aria-rowindex", String(p + 1)), $.setAttribute("aria-level", String(f._depth + 1));
1538
- let P = 0;
1539
- if (o.stateColumn && (P += 24), o.draggable && (P += 18), o.rowNumber && (P += 44), o.checkColumn && (P += 36), P > 0) {
1540
- const w = L("div", "og-group-state-cell");
1541
- w.style.cssText = [
1542
- `width:${P}px;min-width:${P}px;flex-shrink:0;`,
1543
- "display:flex;align-items:center;justify-content:center;",
1544
- "font-size:10px;font-weight:700;gap:2px;",
1545
- "border-right:1px solid var(--og-border-color,#e0e0e0);"
1546
- ].join("");
1547
- const H = f._states ?? { added: 0, edited: 0, removed: 0 };
1548
- if (H.added > 0) {
1549
- const I = L("span");
1550
- I.textContent = `+${H.added}`, I.style.cssText = "color:var(--og-row-added-bg,#2e7d32);background:#e8f5e9;padding:1px 3px;border-radius:3px;", w.appendChild(I);
1551
- }
1552
- if (H.edited > 0) {
1553
- const I = L("span");
1554
- I.textContent = `M${H.edited}`, I.style.cssText = "color:#e65100;background:#fff8e1;padding:1px 3px;border-radius:3px;", w.appendChild(I);
1555
- }
1556
- if (H.removed > 0) {
1557
- const I = L("span");
1558
- I.textContent = `D${H.removed}`, I.style.cssText = "color:var(--og-row-removed-bg,#c62828);background:#ffebee;padding:1px 3px;border-radius:3px;", w.appendChild(I);
1559
- }
1560
- $.appendChild(w);
1561
- }
1562
- let O = !1;
1563
- for (let w = 0; w < i.length; w++) {
1564
- const H = i[w], I = n[w] ?? o.defaultColumnWidth, ie = f._summaryFmt !== void 0 && H.field in (f._summaryFmt ?? {}), B = L("div", "og-group-cell");
1565
- if (B.style.cssText = [
1566
- `width:${I}px;min-width:${I}px;flex-shrink:0;`,
1567
- "padding:2px 8px;box-sizing:border-box;overflow:hidden;",
1568
- "border-right:1px solid var(--og-border-color,#e0e0e0);",
1569
- "display:flex;align-items:center;",
1570
- "white-space:nowrap;text-overflow:ellipsis;"
1571
- ].join(""), ie) {
1572
- const U = f._summaryFmt[H.field];
1573
- B.textContent = U !== "" ? U : "-", B.style.justifyContent = "flex-end", B.style.color = "var(--og-primary,#1976d2)", B.style.fontWeight = "600";
1574
- } else if (!O) {
1575
- O = !0;
1576
- const U = L("span", "og-group-arrow");
1577
- U.textContent = f._expanded ? "▾ " : "▸ ", U.style.cssText = "color:var(--og-primary,#1976d2);margin-right:4px;flex-shrink:0;", B.appendChild(U);
1578
- const j = L("span", "og-group-label");
1579
- j.textContent = `${f._groupLabel} (${f._childCount}건)`, j.style.cssText = "overflow:hidden;text-overflow:ellipsis;font-weight:600;", B.appendChild(j), B.style.gap = "0";
1580
- }
1581
- $.appendChild(B);
1582
- }
1583
- $.addEventListener("click", () => u == null ? void 0 : u(S)), M.appendChild($);
1584
- continue;
1585
- }
1586
- const z = F ? A : null, m = z ? z.data : h ? A : s.getRowByIndex(p);
1587
- if (!m) continue;
1588
- const v = F || T ? "none" : s.getRowState(p), k = L("div", "og-row");
1589
- k.setAttribute("role", "row"), k.setAttribute("aria-rowindex", String(p + 1));
1590
- const K = l + (p - e) * o.rowHeight;
1591
- k.style.top = `${K}px`, k.style.height = `${o.rowHeight}px`;
1592
- let D = p % 2 === 0 ? "var(--og-row-bg,#fff)" : "var(--og-row-alt-bg,#fafafa)";
1593
- k.style.background = D, v === "added" && k.classList.add("og-state-added"), v === "edited" && k.classList.add("og-state-edited"), v === "removed" && k.classList.add("og-state-removed"), a.has(p) && k.classList.add("og-selected"), k.setAttribute("aria-selected", a.has(p) ? "true" : "false"), v === "added" && (D = "var(--og-row-added-bg,#e8f5e9)"), v === "edited" && (D = "var(--og-row-edited-bg,#fff8e1)"), v === "removed" && (D = "var(--og-row-removed-bg,#ffebee)"), a.has(p) && (D = "var(--og-row-selected-bg,#bbdefb)");
1594
- const oe = p;
1595
- k.addEventListener("click", (f) => {
1596
- this._cbs.onCellClick(oe, -1, f);
1597
- });
1598
- const re = /* @__PURE__ */ new Map();
1599
- let V = 0;
1600
- if (o.stateColumn) {
1601
- const f = L("div", "og-cell og-col-state"), S = { added: "✚", edited: "✎", removed: "✖", none: "" }, $ = { added: "#2e7d32", edited: "#bf360c", removed: "#c62828", none: "" };
1602
- f.textContent = S[v] ?? "", f.style.color = $[v] ?? "", f.title = v, C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = D), V += 24, k.appendChild(f);
1603
- }
1604
- const J = this._cbs.getDndManager();
1605
- if (o.draggable && J) {
1606
- const f = J.attachHandle(k, p, o._totalRows ?? t + 1);
1607
- C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = D), V += 18, k.appendChild(f);
1608
- }
1609
- if (o.rowNumber) {
1610
- const f = L("div", "og-cell og-col-rownum");
1611
- f.textContent = String(p + 1), C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = D), V += 44, k.appendChild(f);
1612
- }
1613
- if (o.checkColumn) {
1614
- const f = L("div", "og-cell og-col-check"), S = document.createElement("input");
1615
- S.type = "checkbox", S.checked = c.has(p), S.setAttribute("aria-label", `${p + 1}행 선택`), S.addEventListener("click", ($) => $.stopPropagation()), S.addEventListener("change", ($) => {
1616
- $.stopPropagation(), this._cbs.onRowCheck(p, S.checked);
1617
- }), f.appendChild(S), C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = D), V += 36, k.appendChild(f);
1618
- }
1619
- for (let f = 0; f < i.length; f++) {
1620
- const S = i[f], $ = n[f] ?? o.defaultColumnWidth, se = o.editable && S.editable !== !1, P = f === 0, O = b && !b.isEmpty ? b.getInfo(p, f) : null;
1621
- if (O != null && O.hidden) {
1622
- const R = L("div", "og-cell og-cell--merge-ph");
1623
- R.style.cssText = `width:${$}px;min-width:${$}px;flex-shrink:0;visibility:hidden;box-sizing:border-box;`, k.appendChild(R);
1624
- continue;
1625
- }
1626
- const w = L("div", "og-cell");
1627
- w.setAttribute("role", "gridcell"), w.setAttribute("aria-colindex", String(f + 1));
1628
- const H = (O == null ? void 0 : O.rowSpan) ?? 1, I = (O == null ? void 0 : O.colSpan) ?? 1, ie = H > 1 ? H * o.rowHeight : o.rowHeight;
1629
- let B = $;
1630
- if (I > 1)
1631
- for (let R = 1; R < I; R++)
1632
- B += n[f + R] ?? o.defaultColumnWidth;
1633
- const U = f < C;
1634
- let j = 0;
1635
- if (U) {
1636
- o.stateColumn && (j += 24), o.draggable && (j += 18), o.rowNumber && (j += 44), o.checkColumn && (j += 36);
1637
- for (let R = 0; R < f; R++) j += n[R] ?? o.defaultColumnWidth;
1638
- w.classList.add("og-frozen-cell"), f === C - 1 && w.classList.add("og-frozen-last");
1639
- }
1640
- w.style.width = `${B}px`, w.style.minWidth = `${B}px`, w.style.maxWidth = `${B}px`, H > 1 && (w.style.height = `${ie}px`), U && (w.style.background = D), z && P && (w.style.padding = "0"), w.style.overflow = "hidden", H > 1 ? (w.style.height = `${ie}px`, w.style.position = "absolute", w.style.zIndex = "3", w.style.background = D && D !== "inherit" ? D : "var(--og-row-bg, #fff)", w.style.borderTop = "0", w.style.borderLeft = "0", w.style.borderBottom = "1px solid var(--og-border-color, #e0e0e0)") : U && (w.style.position = "sticky", w.style.left = `${j}px`, w.style.zIndex = "1"), S.type === "number" || S.align === "right" ? w.classList.add("og-cell--right") : S.align === "center" && w.classList.add("og-cell--center"), se && w.classList.add("og-cell--editable"), S.wrap && w.classList.add("og-cell--wrap"), se || w.setAttribute("aria-readonly", "true"), I > 1 && w.setAttribute("aria-colspan", String(I)), H > 1 && w.setAttribute("aria-rowspan", String(H)), ((_ = o._focusCell) == null ? void 0 : _.ri) === p && ((y = o._focusCell) == null ? void 0 : y.ci) === f && (w.classList.add("og-cell-focused"), w.tabIndex = -1);
1641
- const Z = m ? m[S.field] : null;
1642
- w.setAttribute("aria-label", `${S.header}: ${Z == null ? "" : String(Z)}`), S.tooltip != null ? w.title = typeof S.tooltip == "function" ? String(S.tooltip(Z, m) ?? "") : String(S.tooltip) : o.tooltips && Z != null && Z !== "" && (w.title = String(Z));
1643
- let Ce = w;
1644
- if (z && P) {
1645
- const R = L("div", "og-tree-cell"), q = z._ancestorHasMore ?? [];
1646
- for (let N = 0; N < z._depth; N++) {
1647
- const Y = L("span", "og-tree-guide");
1648
- q[N] && Y.classList.add("og-tree-guide--line"), R.appendChild(Y);
1649
- }
1650
- if (z._depth > 0) {
1651
- const N = L("span", "og-tree-connector");
1652
- N.classList.add(
1653
- z._isLastChild ? "og-tree-connector--last" : "og-tree-connector--mid"
1654
- ), R.appendChild(N);
1655
- }
1656
- const ne = L("span", "og-tree-toggle-wrap");
1657
- if (!z._hasChildren) {
1658
- const N = L("span", "og-tree-leaf-dot");
1659
- ne.appendChild(N);
1660
- }
1661
- R.appendChild(ne);
1662
- const W = document.createElement("i");
1663
- if (z._hasChildren) {
1664
- const N = Fe(S.treeNodeIcon, m, !0, z._expanded);
1665
- W.className = z._expanded ? `${N} og-tree-node-icon og-tree-node-icon--branch og-tree-node-icon--open og-tree-node-icon--toggle` : `${N} og-tree-node-icon og-tree-node-icon--branch og-tree-node-icon--toggle`, W.setAttribute("role", "button"), W.setAttribute("tabindex", "0"), W.setAttribute("aria-expanded", z._expanded ? "true" : "false"), W.setAttribute("aria-label", z._expanded ? "접기" : "펼치기"), W.addEventListener("click", (Y) => {
1666
- Y.stopPropagation(), g == null || g(z._treeId);
1667
- }), W.addEventListener("keydown", (Y) => {
1668
- (Y.key === "Enter" || Y.key === " ") && (Y.preventDefault(), Y.stopPropagation(), g == null || g(z._treeId));
1669
- });
1670
- } else {
1671
- const N = Fe(S.treeNodeIcon, m, !1, !1);
1672
- W.setAttribute("aria-hidden", "true"), W.className = `${N} og-tree-node-icon og-tree-node-icon--leaf`;
1673
- }
1674
- R.appendChild(W), w.appendChild(R), Ce = R;
1675
- }
1676
- if (S.cellStyle) {
1677
- const R = m[S.field], q = typeof S.cellStyle == "function" ? S.cellStyle(R, m, p) : S.cellStyle;
1678
- Object.assign(w.style, q);
1679
- }
1680
- const qe = Ct(S).render({
1681
- value: m[S.field],
1682
- row: m,
1683
- rowIndex: p,
1684
- column: S,
1685
- colIndex: f,
1686
- isSelected: a.has(p),
1687
- rowState: v
1688
- });
1689
- Ce.appendChild(qe);
1690
- const X = p, G = f;
1691
- if (w.addEventListener("click", (R) => {
1692
- R.stopPropagation(), this._cbs.onCellClick(X, G, R);
1693
- }), w.addEventListener("dblclick", (R) => {
1694
- R.stopPropagation(), this._cbs.onCellDblClick(X, G, R);
1695
- }), w.addEventListener("mouseover", (R) => {
1696
- R.stopPropagation(), this._cbs.onCellMouseOver(X, G, R);
1697
- }), w.addEventListener("mouseout", (R) => {
1698
- R.stopPropagation(), this._cbs.onCellMouseOut(X, G, R);
1699
- }), w.addEventListener("mousedown", (R) => {
1700
- R.stopPropagation(), this._cbs.onCellMouseDown(X, G, R);
1701
- }), w.addEventListener("mouseup", (R) => {
1702
- R.stopPropagation(), this._cbs.onCellMouseUp(X, G, R);
1703
- }), w.addEventListener("mousemove", (R) => {
1704
- R.stopPropagation(), this._cbs.onCellMouseMove(X, G, R);
1705
- }), re.set(f, w), H > 1) {
1706
- const R = document.createElement("div");
1707
- R.style.cssText = [
1708
- `width:${$}px;min-width:${$}px;height:${o.rowHeight}px;`,
1709
- "flex-shrink:0;box-sizing:border-box;",
1710
- "border-right:1px solid var(--og-border-color,#e0e0e0);"
1711
- ].join(""), k.appendChild(R);
1712
- let q = 0;
1713
- o.stateColumn && (q += 24), o.draggable && (q += 18), o.rowNumber && (q += 44), o.checkColumn && (q += 36);
1714
- for (let W = 0; W < f; W++) q += n[W] ?? o.defaultColumnWidth;
1715
- const ne = l + (p - e) * o.rowHeight;
1716
- w.style.left = `${q}px`, w.style.top = `${ne}px`, M.appendChild(w);
1717
- } else
1718
- k.appendChild(w);
1719
- }
1720
- this._cellMap.set(p, re), M.appendChild(k);
1721
- }
1722
- if (s.rowCount === 0) {
1723
- const p = L("div", "og-empty-message");
1724
- p.textContent = "데이터가 없습니다.", p.style.cssText = "width:100%;", M.appendChild(p);
1725
- }
1726
- this._body.appendChild(M);
1727
- }
1728
- getCellEl(e, t) {
1729
- var s;
1730
- return (s = this._cellMap.get(e)) == null ? void 0 : s.get(t);
1731
- }
1732
- destroy() {
1733
- this._root.innerHTML = "";
1734
- }
1735
- }
1736
- function Fe(d, e, t, s) {
1737
- let i;
1738
- return d ? typeof d == "function" ? i = d(e, t, s) : t ? i = s ? d.branchOpen ?? "bi-folder2-open" : d.branch ?? "bi-folder2" : i = d.leaf ?? "bi-file-earmark" : i = t ? s ? "bi-folder2-open" : "bi-folder2" : "bi-file-earmark", i.startsWith("bi ") ? i : `bi ${i}`;
1739
- }
1740
- function L(d, e) {
1741
- const t = document.createElement(d);
1742
- return e && (t.className = e), t;
1743
- }
1744
- function Te(d, e) {
1745
- Object.assign(d.style, e);
1746
- }
1747
- function De(d, e, t = "text/plain;charset=utf-8") {
1748
- const s = new Blob([d], { type: t }), i = URL.createObjectURL(s), n = document.createElement("a");
1749
- n.href = i, n.download = e, n.click(), URL.revokeObjectURL(i);
1750
- }
1751
- function Rt(d, e, t) {
1752
- let s = 0, i = 0;
1753
- d.addEventListener("mousedown", (n) => {
1754
- n.stopPropagation(), n.preventDefault(), s = n.clientX, i = e.offsetWidth;
1755
- const o = (r) => {
1756
- const a = Math.max(40, i + r.clientX - s);
1757
- e.style.width = `${a}px`, e.style.minWidth = `${a}px`;
1758
- }, l = (r) => {
1759
- document.removeEventListener("mousemove", o), document.removeEventListener("mouseup", l), t(Math.max(40, i + r.clientX - s));
1760
- };
1761
- document.addEventListener("mousemove", o), document.addEventListener("mouseup", l);
1762
- });
1763
- }
1764
- class kt {
1765
- constructor(e) {
1766
- this._selectedRows = /* @__PURE__ */ new Set(), this._checkedRows = /* @__PURE__ */ new Set(), this._data = e;
1767
- }
1768
- // ─── Read-only 접근 ───────────────────────────────────────
1769
- get selectedRows() {
1770
- return this._selectedRows;
1771
- }
1772
- get checkedRows() {
1773
- return this._checkedRows;
1774
- }
1775
- // ─── 선택 변경 ───────────────────────────────────────────
1776
- selectSingle(e) {
1777
- this._selectedRows.clear(), this._selectedRows.add(e);
1778
- }
1779
- selectToggle(e) {
1780
- this._selectedRows.has(e) ? this._selectedRows.delete(e) : this._selectedRows.add(e);
1781
- }
1782
- clearSelection() {
1783
- this._selectedRows.clear();
1784
- }
1785
- // ─── 체크 변경 ───────────────────────────────────────────
1786
- check(e, t) {
1787
- t ? this._checkedRows.add(e) : this._checkedRows.delete(e);
1788
- }
1789
- checkAll(e, t) {
1790
- if (e)
1791
- for (let s = 0; s < t; s++) this._checkedRows.add(s);
1792
- else
1793
- this._checkedRows.clear();
1794
- }
1795
- checkByValue(e, t) {
1796
- for (let s = 0; s < this._data.rowCount; s++)
1797
- t.includes(this._data.getCellValue(s, e)) && this._checkedRows.add(s);
1798
- }
1799
- uncheckAll() {
1800
- this._checkedRows.clear();
1801
- }
1802
- checkById(e) {
1803
- }
1804
- addCheckById(e) {
1805
- }
1806
- uncheckById(e) {
1807
- }
1808
- // ─── 선택 쿼리 API ───────────────────────────────────────
1809
- getSelections() {
1810
- return [...this._selectedRows].map((e) => this._data.getRowByIndex(e)).filter(Boolean);
1811
- }
1812
- getChecked() {
1813
- return [...this._checkedRows].map((e) => ({
1814
- row: this._data.getRowByIndex(e),
1815
- rowIndex: e
1816
- }));
1817
- }
1818
- getAllChecked() {
1819
- return this.getChecked().map((e) => e.row);
1820
- }
1821
- getActiveRow() {
1822
- return this._selectedRows.size > 0 ? [...this._selectedRows][0] : -1;
1823
- }
1824
- activate(e) {
1825
- this._selectedRows.clear(), this._selectedRows.add(e);
1826
- }
1827
- deselect() {
1828
- this._selectedRows.clear();
1829
- }
1830
- // ─── 전체 초기화 (setData / clearData 시) ────────────────
1831
- reset() {
1832
- this._selectedRows.clear(), this._checkedRows.clear();
1833
- }
1834
- }
1835
- class fe {
1836
- constructor() {
1837
- this._onKeyDown = (e) => {
1838
- e.stopPropagation(), e.key === "Enter" ? (e.preventDefault(), this._onCommit(this.input.value)) : e.key === "Escape" && this._onCancel();
1839
- }, this._onBlur = () => {
1840
- this._onCommit(this.input.value);
1841
- };
1842
- }
1843
- mount(e, t, s, i) {
1844
- this._container = e, this._onCommit = s, this._onCancel = i, e.setAttribute("aria-haspopup", "dialog"), e.setAttribute("aria-expanded", "true"), this.input = document.createElement("input"), this.input.type = "date", this.input.className = "og-cell-input", this.input.setAttribute("aria-label", t.column.header ?? "날짜 선택");
1845
- const n = t.value;
1846
- if (n) {
1847
- const o = n instanceof Date ? n : new Date(n);
1848
- isNaN(o.getTime()) || (this.input.value = Ne(o, "yyyy-MM-dd"));
1849
- }
1850
- this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1851
- }
1852
- getValue() {
1853
- var e;
1854
- return (e = this.input) == null ? void 0 : e.value;
1855
- }
1856
- focus() {
1857
- var e;
1858
- (e = this.input) == null || e.focus();
1859
- }
1860
- destroy() {
1861
- var e, t, s;
1862
- (e = this._container) == null || e.setAttribute("aria-expanded", "false"), (t = this.input) == null || t.removeEventListener("keydown", this._onKeyDown), (s = this.input) == null || s.removeEventListener("blur", this._onBlur);
1863
- }
1864
- }
1865
- function $e(d) {
1866
- return d.map((e) => typeof e == "string" ? { label: e, value: e } : { label: e.label ?? e.text ?? String(e.value ?? ""), value: e.value });
1867
- }
1868
- class me {
1869
- constructor(e = [], t) {
1870
- this._options = $e(e), this._optionsFn = t ?? null;
1871
- }
1872
- mount(e, t, s, i) {
1873
- this._container = e, this._onCommit = s, this._onCancel = i, e.setAttribute("aria-haspopup", "listbox"), e.setAttribute("aria-expanded", "true"), this.select = document.createElement("select"), this.select.className = "og-cell-select", this.select.setAttribute("aria-label", t.column.header ?? "선택");
1874
- const n = this._optionsFn ? $e(this._optionsFn(t.row, t.rowIndex)) : this._options;
1875
- for (const l of n) {
1876
- const r = document.createElement("option");
1877
- r.value = String(l.value), r.textContent = l.label, this.select.appendChild(r);
1878
- }
1879
- const o = t.value == null ? "" : String(t.value);
1880
- n.some((l) => String(l.value) === o) && (this.select.value = o), this.select.addEventListener("change", () => s(this.select.value)), this.select.addEventListener("blur", () => s(this.select.value)), this.select.addEventListener("keydown", (l) => {
1881
- l.key === "Escape" && i();
1882
- }), e.appendChild(this.select);
1883
- }
1884
- getValue() {
1885
- var e;
1886
- return (e = this.select) == null ? void 0 : e.value;
1887
- }
1888
- focus() {
1889
- var e;
1890
- (e = this.select) == null || e.focus();
1891
- }
1892
- destroy() {
1893
- var e;
1894
- (e = this._container) == null || e.setAttribute("aria-expanded", "false");
1895
- }
1896
- }
1897
- class be {
1898
- constructor() {
1899
- this._onKeyDown = (e) => {
1900
- e.stopPropagation(), e.key === "Enter" || e.key === "Tab" ? (e.preventDefault(), this._onCommit(this.input.value)) : e.key === "Escape" && this._onCancel();
1901
- }, this._onBlur = () => {
1902
- this._onCommit(this.input.value);
1903
- };
1904
- }
1905
- mount(e, t, s, i) {
1906
- this._onCommit = s, this._onCancel = i, this.input = document.createElement("input"), this.input.type = "text", this.input.value = t.value == null ? "" : String(t.value), this.input.style.cssText = `
1907
- width:100%;height:100%;border:none;outline:none;padding:0 8px;
1908
- font-size:var(--og-font-size,13px);font-family:var(--og-font-family,sans-serif);
1909
- background:var(--og-row-bg,#fff);box-sizing:border-box;
1910
- `, this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1911
- }
1912
- getValue() {
1913
- var e;
1914
- return (e = this.input) == null ? void 0 : e.value;
1915
- }
1916
- focus() {
1917
- var e, t;
1918
- (e = this.input) == null || e.focus(), (t = this.input) == null || t.select();
1919
- }
1920
- destroy() {
1921
- var e, t;
1922
- (e = this.input) == null || e.removeEventListener("keydown", this._onKeyDown), (t = this.input) == null || t.removeEventListener("blur", this._onBlur);
1923
- }
1924
- }
1925
- class we {
1926
- constructor(e) {
1927
- this._onKeyDown = (t) => {
1928
- t.stopPropagation(), t.key === "Enter" || t.key === "Tab" ? (t.preventDefault(), this._commit()) : t.key === "Escape" && this._onCancel();
1929
- }, this._onBlur = () => {
1930
- this._commit();
1931
- }, this.min = e == null ? void 0 : e.min, this.max = e == null ? void 0 : e.max, this.step = e == null ? void 0 : e.step;
1932
- }
1933
- mount(e, t, s, i) {
1934
- this._onCommit = s, this._onCancel = i, this.input = document.createElement("input"), this.input.type = "number", this.input.value = t.value == null ? "" : String(t.value), this.min != null && (this.input.min = String(this.min)), this.max != null && (this.input.max = String(this.max)), this.step != null && (this.input.step = String(this.step)), this.input.style.cssText = `
1935
- width:100%;height:100%;border:none;outline:none;padding:0 8px;
1936
- font-size:var(--og-font-size,13px);text-align:right;
1937
- background:var(--og-row-bg,#fff);box-sizing:border-box;
1938
- `, this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1939
- }
1940
- _commit() {
1941
- const e = this.input.value === "" ? null : Number(this.input.value);
1942
- this._onCommit(e);
1943
- }
1944
- getValue() {
1945
- var e, t;
1946
- return ((e = this.input) == null ? void 0 : e.value) === "" ? null : Number((t = this.input) == null ? void 0 : t.value);
1947
- }
1948
- focus() {
1949
- var e, t;
1950
- (e = this.input) == null || e.focus(), (t = this.input) == null || t.select();
1951
- }
1952
- destroy() {
1953
- var e, t;
1954
- (e = this.input) == null || e.removeEventListener("keydown", this._onKeyDown), (t = this.input) == null || t.removeEventListener("blur", this._onBlur);
1955
- }
1956
- }
1957
- class ye {
1958
- mount(e, t, s, i) {
1959
- this._onCommit = s, e.style.cssText += "display:flex;align-items:center;justify-content:center;", this.chk = document.createElement("input"), this.chk.type = "checkbox", this.chk.checked = !!t.value, this.chk.style.cursor = "pointer", this.chk.addEventListener("change", () => s(this.chk.checked)), e.appendChild(this.chk);
1960
- }
1961
- getValue() {
1962
- var e;
1963
- return (e = this.chk) == null ? void 0 : e.checked;
1964
- }
1965
- focus() {
1966
- var e;
1967
- (e = this.chk) == null || e.focus();
1968
- }
1969
- destroy() {
1970
- }
1971
- }
1972
- function Ae(d) {
1973
- const e = d.editor;
1974
- if (!e)
1975
- switch (d.type) {
1976
- case "number":
1977
- return new we();
1978
- case "date":
1979
- return new fe();
1980
- case "boolean":
1981
- return new ye();
1982
- case "select":
1983
- return new me(d.options ?? [], d.optionsFn);
1984
- default:
1985
- return new be();
1986
- }
1987
- if (typeof e == "string")
1988
- switch (e) {
1989
- case "number":
1990
- return new we();
1991
- case "date":
1992
- return new fe();
1993
- case "select":
1994
- return new me(d.options ?? [], d.optionsFn);
1995
- case "checkbox":
1996
- return new ye();
1997
- default:
1998
- return new be();
1999
- }
2000
- switch (e.type) {
2001
- case "number": {
2002
- const t = {};
2003
- return e.min != null && (t.min = e.min), e.max != null && (t.max = e.max), e.step != null && (t.step = e.step), new we(t);
2004
- }
2005
- case "date":
2006
- return new fe();
2007
- case "select":
2008
- return new me(e.options ?? [], d.optionsFn);
2009
- case "checkbox":
2010
- return new ye();
2011
- default:
2012
- return new be();
2013
- }
2014
- }
2015
- function ee(d) {
2016
- const e = typeof d.renderer == "string" ? d.renderer : d.renderer && typeof d.renderer == "object" ? d.renderer.type : "";
2017
- return d.type === "boolean" || d.type === "checkbox" || e === "checkbox" || e === "switch";
2018
- }
2019
- class Et {
2020
- constructor(e) {
2021
- this._activeEditor = null, this._editCell = null, this._focusCell = null, this._dragColIdx = null, this._d = e;
2022
- }
2023
- // ─── 상태 접근자 ─────────────────────────────────────────
2024
- get activeEditor() {
2025
- return this._activeEditor;
2026
- }
2027
- get editCell() {
2028
- return this._editCell;
2029
- }
2030
- get focusCell() {
2031
- return this._focusCell;
2032
- }
2033
- get dragColIdx() {
2034
- return this._dragColIdx;
2035
- }
2036
- set dragColIdx(e) {
2037
- this._dragColIdx = e;
2038
- }
2039
- // ─── 포커스 셀 ───────────────────────────────────────────
2040
- setFocusCell(e, t) {
2041
- this._focusCell = { ri: e, ci: t }, this._d.scrollToRow(e), this._d.doRender();
2042
- const s = this._d.getVisibleLeaves()[t], i = this._d.data.getRowByIndex(e);
2043
- if (s && i) {
2044
- const n = i[s.field];
2045
- this._d.announce(
2046
- `${e + 1}행 ${t + 1}열, ${s.header}: ${n == null ? "빈 값" : String(n)}`
2047
- );
2048
- }
2049
- }
2050
- clearFocusCell() {
2051
- this._focusCell = null;
2052
- }
2053
- // ─── 편집 시작 (키보드) ──────────────────────────────────
2054
- startEditByKey(e, t) {
2055
- var a, c, h;
2056
- const s = this._d.getVisibleLeaves()[t];
2057
- if (!s) return;
2058
- if (ee(s)) {
2059
- const u = this._d.getOptions();
2060
- if (s.editable !== !1 && (s.editable !== void 0 || u.editable)) {
2061
- const E = this._d.data.getRowByIndex(e);
2062
- E && this._d.writeCell(e, s.field, !E[s.field]);
2063
- }
2064
- return;
2065
- }
2066
- const i = this._d.data.getRowByIndex(e);
2067
- if (s.editable === !1 || typeof s.editable == "function" && !s.editable(i, e)) return;
2068
- this.commitEdit();
2069
- const n = (a = this._d.getRenderer()) == null ? void 0 : a.getCellEl(e, t);
2070
- if (!n) return;
2071
- n.innerHTML = "";
2072
- const o = Ae(s);
2073
- this._activeEditor = o, this._editCell = { ri: e, ci: t };
2074
- const l = {
2075
- type: "editStart",
2076
- rowIndex: e,
2077
- columnIndex: t,
2078
- field: s.field,
2079
- oldValue: i == null ? void 0 : i[s.field],
2080
- newValue: i == null ? void 0 : i[s.field],
2081
- row: i,
2082
- column: s
2083
- };
2084
- this._d.emit("editStart", l), (h = (c = this._d.getOptions()).onEditStart) == null || h.call(c, l), n.classList.add("og-editing");
2085
- const r = {
2086
- value: i == null ? void 0 : i[s.field],
2087
- row: i,
2088
- rowIndex: e,
2089
- column: s,
2090
- colIndex: t,
2091
- isSelected: !0,
2092
- rowState: "none"
2093
- };
2094
- o.mount(
2095
- n,
2096
- r,
2097
- (u) => this.commitEditWithValue(e, t, u),
2098
- () => this.cancelEdit()
2099
- ), requestAnimationFrame(() => o.focus());
2100
- }
2101
- // ─── 편집 시작 (마우스) ──────────────────────────────────
2102
- startEdit(e, t, s) {
2103
- var h, u;
2104
- const i = this._d.getOptions();
2105
- if (!i.editable) return;
2106
- const n = this._d.getVisibleLeaves()[t];
2107
- if (!n || ee(n)) return;
2108
- const o = this._d.data.getRowByIndex(e);
2109
- if (n.editable === !1 || typeof n.editable == "function" && !n.editable(o, e) || !n.editable && !i.editable) return;
2110
- this.commitEdit();
2111
- const l = (h = this._d.getRenderer()) == null ? void 0 : h.getCellEl(e, t);
2112
- if (!l) return;
2113
- l.innerHTML = "";
2114
- const r = Ae(n);
2115
- this._activeEditor = r, this._editCell = { ri: e, ci: t };
2116
- const a = {
2117
- type: "editStart",
2118
- rowIndex: e,
2119
- columnIndex: t,
2120
- field: n.field,
2121
- oldValue: o == null ? void 0 : o[n.field],
2122
- newValue: o == null ? void 0 : o[n.field],
2123
- row: o,
2124
- column: n
2125
- };
2126
- this._d.emit("editStart", a), (u = i.onEditStart) == null || u.call(i, a), l.classList.add("og-editing");
2127
- const c = {
2128
- value: o == null ? void 0 : o[n.field],
2129
- row: o,
2130
- rowIndex: e,
2131
- column: n,
2132
- colIndex: t,
2133
- isSelected: !0,
2134
- rowState: "none"
2135
- };
2136
- r.mount(
2137
- l,
2138
- c,
2139
- (g) => this.commitEditWithValue(e, t, g),
2140
- () => this.cancelEdit()
2141
- ), requestAnimationFrame(() => r.focus());
2142
- }
2143
- // ─── 편집 종료 ───────────────────────────────────────────
2144
- commitEdit() {
2145
- if (!this._activeEditor || !this._editCell) return;
2146
- const e = this._activeEditor.getValue(), { ri: t, ci: s } = this._editCell;
2147
- this._finishEdit(t, s, e, !1);
2148
- }
2149
- commitEditWithValue(e, t, s) {
2150
- this._finishEdit(e, t, s, !1);
2151
- }
2152
- cancelEdit() {
2153
- if (!this._editCell) return;
2154
- const { ri: e, ci: t } = this._editCell;
2155
- this._finishEdit(e, t, void 0, !0);
2156
- }
2157
- _finishEdit(e, t, s, i) {
2158
- var l, r, a;
2159
- if (!this._activeEditor) return;
2160
- const n = this._d.getVisibleLeaves()[t], o = (l = this._d.getRenderer()) == null ? void 0 : l.getCellEl(e, t);
2161
- if (o && (this._activeEditor.destroy(), o.classList.remove("og-editing")), this._activeEditor = null, this._editCell = null, !i && n) {
2162
- const c = this._d.data.getCellValue(e, n.field);
2163
- if (s !== c) {
2164
- this._d.data.updateCell(e, n.field, s);
2165
- const h = this._d.data.getRowByIndex(e), u = this._d.getOptions(), g = {
2166
- type: "editEnd",
2167
- rowIndex: e,
2168
- columnIndex: t,
2169
- field: n.field,
2170
- oldValue: c,
2171
- newValue: s,
2172
- row: h,
2173
- column: n
2174
- };
2175
- this._d.emit("editEnd", g), (r = u.onEditEnd) == null || r.call(u, g), this._d.emit("dataChange", this._d.data.getData()), (a = u.onDataChange) == null || a.call(u, this._d.data.getData());
2176
- }
2177
- }
2178
- this._d.doRender(), requestAnimationFrame(() => this._d.getContainer().focus({ preventScroll: !0 }));
2179
- }
2180
- }
2181
- class St {
2182
- constructor(e, t, s, i, n) {
2183
- this._selects = /* @__PURE__ */ new Map(), this._selected = {}, this._config = t, this._onFilter = s, this._onReset = i, this._el = document.createElement("fieldset"), this._el.className = "og-filter-select";
2184
- const o = document.createElement("legend");
2185
- o.className = "og-filter-select-legend", o.textContent = t.legend ?? "필터", this._el.appendChild(o);
2186
- const l = document.createElement("div");
2187
- l.className = "og-filter-select-row";
2188
- for (const a of t.columns) {
2189
- const c = `og-fsel-${a.field}`, h = document.createElement("div");
2190
- h.className = "og-filter-select-group";
2191
- const u = document.createElement("label");
2192
- u.htmlFor = c, u.textContent = a.label, u.className = "og-filter-select-label";
2193
- const g = document.createElement("select");
2194
- g.id = c, g.className = "og-filter-select-sel", g.setAttribute("aria-label", a.label), n && g.setAttribute("aria-controls", n), a.dependsOn ? this._fill(g, [], !1) : this._fill(g, this._resolve(a, ""), !0), g.addEventListener("change", () => this._onChange(a.field, g.value)), h.appendChild(u), h.appendChild(g), l.appendChild(h), this._selects.set(a.field, g);
2195
- }
2196
- const r = document.createElement("button");
2197
- r.type = "button", r.textContent = "초기화", r.className = "og-filter-select-reset", r.setAttribute("aria-label", "필터 초기화"), r.addEventListener("click", () => this._reset()), this._el.appendChild(l), this._el.appendChild(r), e.insertBefore(this._el, e.firstChild);
2198
- }
2199
- // ─── 옵션 해결 ────────────────────────────────────────
2200
- /**
2201
- * 컬럼의 옵션 목록을 계산한다.
2202
- *
2203
- * @param col 대상 컬럼 정의
2204
- * @param parentValue 부모 선택값 (캐스케이딩 필터에 사용)
2205
- */
2206
- _resolve(e, t) {
2207
- if (e.options) return e.options;
2208
- let s = e.data ?? [];
2209
- e.dependsOn && e.dependsOnKey && t && (s = s.filter(
2210
- (o) => String(o[e.dependsOnKey] ?? "") === t
2211
- ));
2212
- const i = e.valueKey ?? "value", n = e.textKey ?? i;
2213
- return s.map((o) => ({
2214
- value: String(o[i] ?? ""),
2215
- text: String(o[n] ?? o[i] ?? "")
2216
- }));
2217
- }
2218
- // ─── select DOM 채우기 ────────────────────────────────
2219
- _fill(e, t, s) {
2220
- e.innerHTML = "";
2221
- const i = document.createElement("option");
2222
- i.value = "", i.textContent = "전체", e.appendChild(i);
2223
- for (const n of t) {
2224
- const o = document.createElement("option");
2225
- o.value = n.value, o.textContent = n.text, e.appendChild(o);
2226
- }
2227
- e.disabled = !s;
2228
- }
2229
- // ─── 선택 변경 처리 ───────────────────────────────────
2230
- _onChange(e, t) {
2231
- const s = this._config.columns.find((n) => n.field === e), i = s.filterKey ?? s.field;
2232
- t ? (this._selected[e] = t, this._onFilter(i, [{ operator: "=", value: t }])) : (delete this._selected[e], this._onReset(i)), this._cascade(e);
2233
- }
2234
- /**
2235
- * 부모 컬럼 변경 후 자식 컬럼 옵션을 재계산한다 (재귀).
2236
- */
2237
- _cascade(e) {
2238
- const t = this._selected[e] ?? "";
2239
- for (const s of this._config.columns) {
2240
- if (s.dependsOn !== e) continue;
2241
- const i = this._selects.get(s.field);
2242
- if (!i) continue;
2243
- const n = s.filterKey ?? s.field;
2244
- t ? (this._fill(i, this._resolve(s, t), !0), i.value = "", delete this._selected[s.field], this._onReset(n)) : (this._fill(i, [], !1), delete this._selected[s.field], this._onReset(n), this._cascade(s.field));
2245
- }
2246
- }
2247
- // ─── 전체 초기화 ──────────────────────────────────────
2248
- _reset() {
2249
- this._selected = {};
2250
- for (const e of this._config.columns) {
2251
- const t = this._selects.get(e.field), s = e.filterKey ?? e.field;
2252
- t && (e.dependsOn ? this._fill(t, [], !1) : (t.value = "", t.disabled = !1), this._onReset(s));
2253
- }
2254
- }
2255
- // ─── 공개 API ─────────────────────────────────────────
2256
- reset() {
2257
- this._reset();
2258
- }
2259
- destroy() {
2260
- this._el.remove();
2261
- }
2262
- }
2263
- class Lt {
2264
- constructor(e, t, s) {
2265
- this._page = 1, this._totalRows = 0, this._pageSize = t, this._onChange = s, this._el = document.createElement("div"), this._el.className = "og-pagination", this._el.style.cssText = `
2266
- display:flex;align-items:center;justify-content:center;gap:4px;
2267
- padding:6px 8px;border-top:1px solid var(--og-border-color,#e0e0e0);
2268
- background:var(--og-header-bg,#f5f5f5);flex-shrink:0;user-select:none;
2269
- font-size:12px;color:var(--og-text-color,#333);
2270
- `, e.appendChild(this._el), this._render();
2271
- }
2272
- get page() {
2273
- return this._page;
2274
- }
2275
- get pageSize() {
2276
- return this._pageSize;
2277
- }
2278
- get totalPages() {
2279
- return Math.max(1, Math.ceil(this._totalRows / this._pageSize));
2280
- }
2281
- /** 전체 행 수 갱신 → 현재 페이지 유효성 검사 후 재렌더 */
2282
- setTotalRows(e) {
2283
- this._totalRows = e, this._page > this.totalPages && (this._page = this.totalPages), this._render();
2284
- }
2285
- setPageSize(e) {
2286
- this._pageSize = e, this._page = 1, this._render(), this._emit();
2287
- }
2288
- goTo(e) {
2289
- const t = Math.max(1, Math.min(e, this.totalPages));
2290
- t !== this._page && (this._page = t, this._render(), this._emit());
2291
- }
2292
- /** 현재 페이지의 [startIndex, endIndex] 반환 (DataLayer 인덱스 기준) */
2293
- getRange() {
2294
- const e = (this._page - 1) * this._pageSize, t = Math.min(e + this._pageSize - 1, this._totalRows - 1);
2295
- return { start: e, end: t };
2296
- }
2297
- _emit() {
2298
- this._onChange({
2299
- page: this._page,
2300
- pageSize: this._pageSize,
2301
- totalRows: this._totalRows,
2302
- totalPages: this.totalPages
2303
- });
2304
- }
2305
- _render() {
2306
- this._el.innerHTML = "";
2307
- const e = this.totalPages, t = document.createElement("span");
2308
- t.style.cssText = "display:flex;align-items:center;gap:3px;margin-right:8px;";
2309
- const s = document.createElement("span");
2310
- s.textContent = "행/페이지:", s.style.color = "#888";
2311
- const i = document.createElement("select");
2312
- i.style.cssText = "padding:2px 4px;border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;font-size:11px;cursor:pointer;";
2313
- for (const c of [10, 20, 50, 100, 200]) {
2314
- const h = document.createElement("option");
2315
- h.value = String(c), h.textContent = String(c), c === this._pageSize && (h.selected = !0), i.appendChild(h);
2316
- }
2317
- i.addEventListener("change", () => this.setPageSize(Number(i.value))), t.appendChild(s), t.appendChild(i), this._el.appendChild(t);
2318
- const n = document.createElement("span"), { start: o, end: l } = this.getRange();
2319
- n.textContent = this._totalRows > 0 ? `${o + 1}–${l + 1} / ${this._totalRows}건` : "0건", n.style.cssText = "margin-right:8px;color:#888;", this._el.appendChild(n);
2320
- const r = (c, h, u) => {
2321
- const g = document.createElement("button");
2322
- return g.textContent = c, g.disabled = u, g.style.cssText = `
2323
- min-width:28px;height:24px;padding:0 6px;
2324
- border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;
2325
- background:${u ? "#f5f5f5" : "#fff"};
2326
- color:${u ? "#bbb" : "var(--og-text-color,#333)"};
2327
- cursor:${u ? "default" : "pointer"};font-size:12px;
2328
- `, u || g.addEventListener("click", () => this.goTo(h)), g;
2329
- };
2330
- this._el.appendChild(r("«", 1, this._page === 1)), this._el.appendChild(r("‹", this._page - 1, this._page === 1));
2331
- const a = Ft(this._page, e);
2332
- for (const c of a)
2333
- if (c === -1) {
2334
- const h = document.createElement("span");
2335
- h.textContent = "…", h.style.padding = "0 3px", this._el.appendChild(h);
2336
- } else {
2337
- const h = r(String(c), c, c === this._page);
2338
- c === this._page && (h.style.background = "var(--og-primary,#1976d2)", h.style.color = "#fff", h.style.borderColor = "var(--og-primary,#1976d2)"), this._el.appendChild(h);
2339
- }
2340
- this._el.appendChild(r("›", this._page + 1, this._page === e)), this._el.appendChild(r("»", e, this._page === e));
2341
- }
2342
- destroy() {
2343
- this._el.remove();
2344
- }
2345
- }
2346
- function Ft(d, e) {
2347
- if (e <= 7) return Array.from({ length: e }, (s, i) => i + 1);
2348
- const t = [1];
2349
- d > 3 && t.push(-1);
2350
- for (let s = Math.max(2, d - 1); s <= Math.min(e - 1, d + 1); s++)
2351
- t.push(s);
2352
- return d < e - 2 && t.push(-1), t.push(e), t;
2353
- }
2354
- class Tt {
2355
- constructor(e, t, s) {
2356
- this._drag = null, this._bodyEl = e, this._rowHeight = t, this._onDrop = s, this._onMouseMove = this._onMouseMove.bind(this), this._onMouseUp = this._onMouseUp.bind(this);
2357
- }
2358
- /** 행 엘리먼트에 드래그 핸들 삽입 */
2359
- attachHandle(e, t, s) {
2360
- const i = document.createElement("div");
2361
- return i.className = "og-drag-handle", i.innerHTML = "⠿", i.style.cssText = `
2362
- width:18px;min-width:18px;height:100%;
2363
- display:flex;align-items:center;justify-content:center;
2364
- cursor:grab;font-size:14px;color:#bbb;flex-shrink:0;
2365
- user-select:none;border-right:1px solid var(--og-border-color,#e0e0e0);
2366
- `, i.addEventListener("mousedown", (n) => {
2367
- n.preventDefault(), n.stopPropagation(), this._startDrag(n, e, t, s);
2368
- }), i;
2369
- }
2370
- _startDrag(e, t, s, i) {
2371
- const n = t.getBoundingClientRect(), o = document.createElement("div");
2372
- o.style.cssText = `
2373
- position:fixed;left:${n.left}px;top:${n.top}px;
2374
- width:${n.width}px;height:${n.height}px;
2375
- background:rgba(25,118,210,0.12);border:2px dashed #1976d2;
2376
- box-sizing:border-box;pointer-events:none;z-index:9999;
2377
- border-radius:2px;opacity:0.9;
2378
- `, document.body.appendChild(o);
2379
- const l = document.createElement("div");
2380
- l.style.cssText = `
2381
- position:absolute;left:0;right:0;height:2px;
2382
- background:#1976d2;pointer-events:none;z-index:9998;display:none;
2383
- `, this._bodyEl.appendChild(l), this._drag = {
2384
- fromIndex: s,
2385
- startY: e.clientY,
2386
- ghostEl: o,
2387
- indicator: l,
2388
- rowHeight: this._rowHeight,
2389
- totalRows: i,
2390
- bodyEl: this._bodyEl,
2391
- currentTarget: s
2392
- }, document.addEventListener("mousemove", this._onMouseMove), document.addEventListener("mouseup", this._onMouseUp);
2393
- }
2394
- _onMouseMove(e) {
2395
- if (!this._drag) return;
2396
- const t = this._drag, s = e.clientY - t.startY, i = t.ghostEl.getBoundingClientRect();
2397
- t.ghostEl.style.top = `${i.top + s}px`, t.startY = e.clientY;
2398
- const n = t.bodyEl.getBoundingClientRect(), o = e.clientY - n.top + t.bodyEl.scrollTop, l = Math.max(0, Math.min(t.totalRows - 1, Math.round(o / t.rowHeight)));
2399
- t.currentTarget = l;
2400
- const r = l * t.rowHeight;
2401
- t.indicator.style.display = "block", t.indicator.style.top = `${r}px`;
2402
- }
2403
- _onMouseUp(e) {
2404
- if (document.removeEventListener("mousemove", this._onMouseMove), document.removeEventListener("mouseup", this._onMouseUp), !this._drag) return;
2405
- const { fromIndex: t, currentTarget: s, ghostEl: i, indicator: n } = this._drag;
2406
- this._drag = null, i.remove(), n.remove(), t !== s && this._onDrop(t, s);
2407
- }
2408
- destroy() {
2409
- var e, t;
2410
- document.removeEventListener("mousemove", this._onMouseMove), document.removeEventListener("mouseup", this._onMouseUp), (e = this._drag) == null || e.ghostEl.remove(), (t = this._drag) == null || t.indicator.remove(), this._drag = null;
2411
- }
2412
- }
2413
- class Q {
2414
- constructor() {
2415
- this._map = /* @__PURE__ */ new Map();
2416
- }
2417
- static _key(e, t) {
2418
- return `${e}:${t}`;
2419
- }
2420
- /** 수동 병합 정의 목록으로 맵 구성 */
2421
- applyMergeCells(e) {
2422
- this._map.clear();
2423
- for (const t of e) {
2424
- const s = Math.max(1, t.rowSpan ?? 1), i = Math.max(1, t.colSpan ?? 1);
2425
- this._map.set(Q._key(t.row, t.col), {
2426
- rowSpan: s,
2427
- colSpan: i,
2428
- hidden: !1
2429
- });
2430
- for (let n = 0; n < s; n++)
2431
- for (let o = 0; o < i; o++)
2432
- n === 0 && o === 0 || this._map.set(Q._key(t.row + n, t.col + o), {
2433
- rowSpan: 1,
2434
- colSpan: 1,
2435
- hidden: !0
2436
- });
2437
- }
2438
- }
2439
- /**
2440
- * 자동 병합: 지정 컬럼 인덱스 목록에 대해 연속 같은 값을 rowSpan으로 병합.
2441
- * data: 현재 표시 순서의 행 배열, colIndexes: 자동병합할 leaf 컬럼 인덱스
2442
- * fields: colIndexes[i] 에 대응하는 field 이름
2443
- */
2444
- applyAutoMerge(e, t, s) {
2445
- var i, n;
2446
- this._map.clear();
2447
- for (let o = 0; o < t.length; o++) {
2448
- const l = t[o], r = s[o];
2449
- let a = 0;
2450
- for (let c = 1; c <= e.length; c++) {
2451
- const h = (i = e[c - 1]) == null ? void 0 : i[r], u = c < e.length ? (n = e[c]) == null ? void 0 : n[r] : void 0;
2452
- if (c === e.length || u !== h) {
2453
- const g = c - a;
2454
- if (g > 1) {
2455
- this._map.set(Q._key(a, l), {
2456
- rowSpan: g,
2457
- colSpan: 1,
2458
- hidden: !1
2459
- });
2460
- for (let E = a + 1; E < c; E++)
2461
- this._map.set(Q._key(E, l), {
2462
- rowSpan: 1,
2463
- colSpan: 1,
2464
- hidden: !0
2465
- });
2466
- }
2467
- a = c;
2468
- }
2469
- }
2470
- }
2471
- }
2472
- /** 셀 병합 정보 조회. 없으면 null */
2473
- getInfo(e, t) {
2474
- return this._map.get(Q._key(e, t)) ?? null;
2475
- }
2476
- /** 병합 맵 초기화 */
2477
- clear() {
2478
- this._map.clear();
2479
- }
2480
- get isEmpty() {
2481
- return this._map.size === 0;
2482
- }
2483
- }
2484
- const Dt = [
2485
- { id: "sort-asc", label: "오름차순 정렬", icon: "↑", action: "sortAsc" },
2486
- { id: "sort-desc", label: "내림차순 정렬", icon: "↓", action: "sortDesc" },
2487
- { type: "divider" },
2488
- { id: "find", label: "찾기", icon: "🔍", action: "find" },
2489
- { type: "divider" },
2490
- { id: "excel", label: "Excel로 저장", icon: "📊", action: "excel" },
2491
- { id: "csv", label: "CSV로 저장", icon: "📄", action: "csv" },
2492
- { id: "print", label: "인쇄", icon: "🖨", action: "print" }
2493
- ];
2494
- class $t {
2495
- /**
2496
- * @param _anchor 그리드 컨테이너 엘리먼트 — CSS 변수 상속 기준점
2497
- * @param _actions 기본 액션 핸들러 (OpenGrid에서 주입)
2498
- */
2499
- constructor(e, t) {
2500
- this._anchor = e, this._actions = t, this._el = null, this._docClick = null, this._docKey = null, this._docScroll = null, this._docMouseMove = null, this._focusIdx = -1;
2501
- }
2502
- open(e, t) {
2503
- this.close();
2504
- const s = t ?? Dt, i = document.createElement("div");
2505
- i.className = "og-context-menu", i.setAttribute("role", "menu");
2506
- for (const l of s) {
2507
- if (l.type === "divider") {
2508
- const c = document.createElement("div");
2509
- c.className = "og-cm-divider", c.setAttribute("role", "separator"), i.appendChild(c);
2510
- continue;
2511
- }
2512
- const r = document.createElement("button");
2513
- if (r.className = "og-cm-item", r.setAttribute("role", "menuitem"), r.setAttribute("tabindex", "-1"), l.disabled && (r.classList.add("og-cm-disabled"), r.setAttribute("aria-disabled", "true")), l.icon) {
2514
- const c = document.createElement("span");
2515
- if (c.className = "og-cm-icon", /^[a-zA-Z][\w-]*(\s+[\w-]+)+$/.test(l.icon.trim())) {
2516
- const h = document.createElement("i");
2517
- h.className = l.icon, c.appendChild(h);
2518
- } else
2519
- c.textContent = l.icon;
2520
- c.setAttribute("aria-hidden", "true"), r.appendChild(c);
2521
- }
2522
- const a = document.createElement("span");
2523
- a.className = "og-cm-label", a.textContent = l.label ?? "", r.appendChild(a), r.addEventListener("click", (c) => {
2524
- c.stopPropagation(), l.disabled || this._runAction(l), this.close();
2525
- }), i.appendChild(r);
2526
- }
2527
- const n = this._anchor.closest("[data-og-theme]"), o = n == null ? void 0 : n.getAttribute("data-og-theme");
2528
- o && i.setAttribute("data-og-theme", o), document.body.appendChild(i), this._el = i, this._docMouseMove = (l) => {
2529
- if (!this._el) return;
2530
- const r = this._el.getBoundingClientRect();
2531
- (l.clientX < r.left - 4 || l.clientX > r.right + 4 || l.clientY < r.top - 4 || l.clientY > r.bottom + 4) && this.close();
2532
- }, this._position(i, e.clientX, e.clientY, () => {
2533
- this._el === i && document.addEventListener("mousemove", this._docMouseMove, { capture: !0, passive: !0 });
2534
- }), this._docClick = (l) => {
2535
- i.contains(l.target) || this.close();
2536
- }, this._docKey = (l) => {
2537
- if (l.key === "Escape") {
2538
- this.close();
2539
- return;
2540
- }
2541
- if (l.key === "ArrowDown") {
2542
- l.preventDefault(), this._moveFocus(1);
2543
- return;
2544
- }
2545
- if (l.key === "ArrowUp") {
2546
- l.preventDefault(), this._moveFocus(-1);
2547
- return;
2548
- }
2549
- if (l.key === "Enter") {
2550
- const r = i.querySelector(".og-cm-item:focus");
2551
- r == null || r.click();
2552
- }
2553
- }, this._docScroll = () => this.close(), setTimeout(() => {
2554
- document.addEventListener("click", this._docClick), document.addEventListener("keydown", this._docKey), window.addEventListener("scroll", this._docScroll, { passive: !0 });
2555
- }, 0), this._focusIdx = -1, this._moveFocus(1);
2556
- }
2557
- close() {
2558
- var e;
2559
- (e = this._el) == null || e.remove(), this._el = null, this._docClick && document.removeEventListener("click", this._docClick), this._docKey && document.removeEventListener("keydown", this._docKey), this._docScroll && window.removeEventListener("scroll", this._docScroll), this._docMouseMove && document.removeEventListener("mousemove", this._docMouseMove, { capture: !0 }), this._docClick = this._docKey = this._docScroll = this._docMouseMove = null, this._focusIdx = -1;
2560
- }
2561
- destroy() {
2562
- this.close();
2563
- }
2564
- // ── 위치 결정 ─────────────────────────────────────────────
2565
- _position(e, t, s, i) {
2566
- e.style.cssText = "position:fixed;visibility:hidden;left:0;top:0;", requestAnimationFrame(() => {
2567
- const { width: n, height: o } = e.getBoundingClientRect(), l = window.innerWidth, r = window.innerHeight, a = t + n > l ? Math.max(0, t - n) : t, c = s + o > r ? Math.max(0, s - o) : s;
2568
- e.style.cssText = `position:fixed;left:${a}px;top:${c}px;z-index:9999;`, i == null || i();
2569
- });
2570
- }
2571
- // ── 키보드 포커스 이동 ────────────────────────────────────
2572
- _moveFocus(e) {
2573
- var s;
2574
- if (!this._el) return;
2575
- const t = Array.from(
2576
- this._el.querySelectorAll(".og-cm-item:not(.og-cm-disabled)")
2577
- );
2578
- t.length && (this._focusIdx = (this._focusIdx + e + t.length) % t.length, (s = t[this._focusIdx]) == null || s.focus());
2579
- }
2580
- // ── 액션 실행 ─────────────────────────────────────────────
2581
- _runAction(e) {
2582
- if (typeof e.action == "function") {
2583
- e.action();
2584
- return;
2585
- }
2586
- switch (e.action) {
2587
- case "sortAsc":
2588
- this._actions.onSortAsc();
2589
- break;
2590
- case "sortDesc":
2591
- this._actions.onSortDesc();
2592
- break;
2593
- case "find":
2594
- this._actions.onFind();
2595
- break;
2596
- case "excel":
2597
- this._actions.onExcel();
2598
- break;
2599
- case "csv":
2600
- this._actions.onCsv();
2601
- break;
2602
- case "print":
2603
- this._actions.onPrint();
2604
- break;
2605
- }
2606
- }
2607
- }
2608
- class ze {
2609
- constructor(e, t) {
2610
- this._sheets = /* @__PURE__ */ new Map(), this._active = "", this._onSwitch = t, this._tabBar = this._buildTabBar(e);
2611
- }
2612
- // ── 시트 CRUD ────────────────────────────────────────────
2613
- add(e, t = [], s = []) {
2614
- if (this._sheets.has(e))
2615
- throw new Error(`WorksheetManager: 시트 '${e}'이 이미 존재합니다`);
2616
- this._sheets.set(e, { name: e, columns: t, data: s }), this._renderTabs(), this._sheets.size === 1 && this.switch(e);
2617
- }
2618
- remove(e) {
2619
- if (!this._sheets.has(e)) return;
2620
- if (this._sheets.size === 1)
2621
- throw new Error("WorksheetManager: 마지막 시트는 삭제할 수 없습니다");
2622
- const t = this._active === e;
2623
- this._sheets.delete(e), this._renderTabs(), t && this.switch(this._sheets.keys().next().value);
2624
- }
2625
- rename(e, t) {
2626
- if (!this._sheets.has(e)) return;
2627
- if (this._sheets.has(t))
2628
- throw new Error(`WorksheetManager: 시트 '${t}'이 이미 존재합니다`);
2629
- this._sheets.get(e);
2630
- const s = Array.from(this._sheets.entries()).map(
2631
- ([i, n]) => i === e ? [t, { ...n, name: t }] : [i, n]
2632
- );
2633
- this._sheets = new Map(s), this._active === e && (this._active = t), this._renderTabs();
2634
- }
2635
- switch(e) {
2636
- const t = this._sheets.get(e);
2637
- if (!t) throw new Error(`WorksheetManager: 시트 '${e}'을 찾을 수 없습니다`);
2638
- this._active = e, this._renderTabs(), this._onSwitch(e, t);
2639
- }
2640
- get(e) {
2641
- return this._sheets.get(e);
2642
- }
2643
- getNames() {
2644
- return Array.from(this._sheets.keys());
2645
- }
2646
- getActive() {
2647
- return this._active;
2648
- }
2649
- /** 현재 활성 시트의 data를 갱신 (그리드 편집 동기화용) */
2650
- syncData(e, t) {
2651
- const s = this._sheets.get(e);
2652
- s && (s.data = t);
2653
- }
2654
- destroy() {
2655
- this._tabBar.remove();
2656
- }
2657
- // ── 탭 UI ────────────────────────────────────────────────
2658
- _buildTabBar(e) {
2659
- const t = document.createElement("div");
2660
- return t.className = "og-sheet-tabs", e.appendChild(t), t;
2661
- }
2662
- _renderTabs() {
2663
- this._tabBar.innerHTML = "";
2664
- for (const t of this._sheets.keys()) {
2665
- const s = document.createElement("button");
2666
- s.className = "og-sheet-tab", s.textContent = t, s.setAttribute("role", "tab"), s.setAttribute("aria-selected", t === this._active ? "true" : "false"), t === this._active && s.classList.add("og-sheet-tab--active"), s.addEventListener("click", () => {
2667
- t !== this._active && this.switch(t);
2668
- }), s.addEventListener("dblclick", () => this._startRename(s, t)), this._tabBar.appendChild(s);
2669
- }
2670
- const e = document.createElement("button");
2671
- e.className = "og-sheet-add", e.textContent = "+", e.setAttribute("aria-label", "새 워크시트 추가"), e.addEventListener("click", () => {
2672
- const t = `Sheet${this._sheets.size + 1}`;
2673
- this.add(t, [], []), this.switch(t);
2674
- }), this._tabBar.appendChild(e);
2675
- }
2676
- /** 탭 더블클릭 → input으로 전환해 이름 변경 */
2677
- _startRename(e, t) {
2678
- const s = document.createElement("input");
2679
- s.className = "og-sheet-tab-rename", s.value = t, e.replaceWith(s), s.focus(), s.select();
2680
- const i = () => {
2681
- const n = s.value.trim() || t;
2682
- try {
2683
- n !== t ? this.rename(t, n) : this._renderTabs();
2684
- } catch {
2685
- this._renderTabs();
2686
- }
2687
- };
2688
- s.addEventListener("blur", i), s.addEventListener("keydown", (n) => {
2689
- n.key === "Enter" && s.blur(), n.key === "Escape" && (s.value = t, s.blur());
2690
- });
2691
- }
2692
- }
2693
- class At {
2694
- constructor(e) {
2695
- this._d = e;
2696
- }
2697
- _readCssVar(e) {
2698
- return getComputedStyle(this._d.getContainer()).getPropertyValue(e).trim();
2699
- }
2700
- _hexToXlsxRgb(e) {
2701
- const t = e.trim(), s = t.match(/^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)/i);
2702
- if (s)
2703
- return [s[1], s[2], s[3]].map((n) => parseInt(n).toString(16).padStart(2, "0")).join("").toUpperCase();
2704
- const i = t.replace("#", "").toUpperCase();
2705
- return i.length === 3 ? i[0] + i[0] + i[1] + i[1] + i[2] + i[2] : i.length === 6 ? i : "";
2706
- }
2707
- exportExcel(e) {
2708
- const t = typeof e == "string" ? { filename: e } : e ?? {};
2709
- let s = t.filename ?? "export";
2710
- s.toLowerCase().endsWith(".xlsx") || (s += ".xlsx");
2711
- const i = t.sheetName ?? (this._d.getOptions().ariaLabel || "Sheet1"), n = this._d.getData(), o = this._d.getColLayout().visibleLeaves.filter((r) => {
2712
- var a;
2713
- return !((a = t.exceptFields) != null && a.includes(r.field));
2714
- }), l = t.includeHeader !== !1;
2715
- import("./xlsx.min-Wavxcamn.js").then((r) => r.x).then(({ utils: r, writeFile: a }) => {
2716
- var m;
2717
- const c = [];
2718
- l && c.push(o.map((v) => v.header));
2719
- for (const v of n)
2720
- c.push(o.map((k) => {
2721
- const K = v[k.field];
2722
- if (t.maskOnExport && k.mask && this._d.getMaskEnabled(k.field))
2723
- return ve(K == null ? "" : String(K), k.mask);
2724
- const D = K;
2725
- return D == null || D === "" ? "" : k.type === "number" && typeof D == "number" ? D : typeof D == "boolean" ? D ? "✓" : "" : typeof D == "object" ? "" : String(D);
2726
- }));
2727
- const h = r.aoa_to_sheet(c), u = this._d.getColWidths(), g = this._d.getColLayout();
2728
- h["!cols"] = o.map((v) => ({
2729
- wpx: u[g.getColumnIndex(v.field)] ?? 100
2730
- })), h["!rows"] = c.map((v, k) => ({ hpx: k === 0 && l ? 22 : 19 }));
2731
- const E = t.styleMode ?? "theme";
2732
- let b = "1565C0", C = "FFFFFF", M = "FFFFFF", _ = "EEF2FF", y = "212121", p = "BDBDBD", A = 10;
2733
- if (E === "theme") {
2734
- const v = (K) => this._hexToXlsxRgb(K);
2735
- b = v(this._readCssVar("--og-header-bg")) || b, C = v(this._readCssVar("--og-header-color")) || C, M = v(this._readCssVar("--og-row-bg")) || M, _ = v(this._readCssVar("--og-row-alt-bg")) || _, y = v(this._readCssVar("--og-row-color")) || y, p = v(this._readCssVar("--og-border-color")) || p;
2736
- const k = this._readCssVar("--og-font-size");
2737
- k && (A = Math.max(8, Math.round(parseFloat(k) * 0.75)));
2738
- }
2739
- const T = E === "none", F = {
2740
- hdrFont: T ? {} : { bold: !0, color: { rgb: C }, sz: A, name: "맑은 고딕" },
2741
- dataFont: T ? {} : { sz: A, color: { rgb: y }, name: "맑은 고딕" },
2742
- hdrFill: T ? {} : { patternType: "solid", fgColor: { rgb: b } },
2743
- evenFill: T ? {} : { patternType: "solid", fgColor: { rgb: M } },
2744
- oddFill: T ? {} : { patternType: "solid", fgColor: { rgb: _ } },
2745
- hdrBorder: T ? {} : {
2746
- top: { style: "medium", color: { rgb: b } },
2747
- bottom: { style: "medium", color: { rgb: b } },
2748
- left: { style: "thin", color: { rgb: b } },
2749
- right: { style: "thin", color: { rgb: b } }
2750
- },
2751
- dataBorder: T ? {} : {
2752
- top: { style: "thin", color: { rgb: p } },
2753
- bottom: { style: "thin", color: { rgb: p } },
2754
- left: { style: "thin", color: { rgb: p } },
2755
- right: { style: "thin", color: { rgb: p } }
2756
- }
2757
- };
2758
- c.forEach((v, k) => {
2759
- const K = l && k === 0, oe = (l ? k - 1 : k) % 2 === 0;
2760
- v.forEach((re, V) => {
2761
- const J = r.encode_cell({ r: k, c: V });
2762
- h[J] || (h[J] = { t: "s", v: "" });
2763
- const f = o[V], S = f.type === "number" || f.align === "right", $ = K ? "center" : S ? "right" : f.align ?? "left";
2764
- h[J].s = {
2765
- font: K ? F.hdrFont : F.dataFont,
2766
- fill: K ? F.hdrFill : oe ? F.evenFill : F.oddFill,
2767
- border: K ? F.hdrBorder : F.dataBorder,
2768
- alignment: { horizontal: $, vertical: "center", wrapText: !1 }
2769
- };
2770
- });
2771
- });
2772
- const z = r.book_new();
2773
- r.book_append_sheet(z, h, i), a(z, s, { cellStyles: !0 }), (m = t.onAfter) == null || m.call(t, new Blob([]));
2774
- }).catch(() => {
2775
- console.error("Excel 내보내기 실패: xlsx 패키지를 확인하세요.");
2776
- });
2777
- }
2778
- exportCsv(e) {
2779
- const t = typeof e == "string" ? { filename: e } : e ?? {}, s = this._d.getData(), i = this._d.getColLayout().visibleLeaves, n = i.map((r) => `"${r.header}"`).join(","), o = s.map((r) => i.map((a) => {
2780
- const c = r[a.field] ?? "";
2781
- if (t.maskOnExport && a.mask && this._d.getMaskEnabled(a.field))
2782
- return ve(String(c), a.mask);
2783
- const h = c;
2784
- return typeof h == "string" && h.includes(",") ? `"${h}"` : h;
2785
- }).join(",")), l = t.filename ?? "export.csv";
2786
- De("\uFEFF" + [n, ...o].join(`
2787
- `), l);
2788
- }
2789
- exportJson(e) {
2790
- const t = typeof e == "string" ? e : (e == null ? void 0 : e.filename) ?? "export.json";
2791
- De(JSON.stringify(this._d.getData(), null, 2), t, "application/json");
2792
- }
2793
- print(e) {
2794
- const t = (e == null ? void 0 : e.title) ?? "OPEN_GRID", s = (e == null ? void 0 : e.footerText) ?? "", i = this._d.getData(), n = this._d.getColLayout().visibleLeaves.filter((h) => {
2795
- var u;
2796
- return !((u = e == null ? void 0 : e.excludeFields) != null && u.includes(h.field));
2797
- }), o = n.map((h) => `<th>${h.header ?? h.field}</th>`).join(""), l = i.map(
2798
- (h) => `<tr>${n.map((u) => `<td>${String(h[u.field] ?? "")}</td>`).join("")}</tr>`
2799
- ).join(""), r = s ? `<div class="og-print-footer">${s}</div>` : "", a = `<!DOCTYPE html>
2800
- <html lang="ko"><head>
2801
- <meta charset="UTF-8"><title>${t}</title>
2802
- <style>
2803
- @page{margin:0;}
2804
- body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:12px;margin:0;padding:1cm;}
2805
- h2{margin:0 0 10px;font-size:14px;color:#333;}
2806
- p{margin:0 0 8px;font-size:11px;color:#999;}
2807
- table{border-collapse:collapse;width:100%;}
2808
- th,td{border:1px solid #ccc;padding:5px 8px;text-align:left;white-space:nowrap;}
2809
- th{background:#f5f5f5;font-weight:600;color:#333;}
2810
- tr:nth-child(even) td{background:#fafafa;}
2811
- .og-print-footer{position:fixed;bottom:0;left:0;right:0;padding:6px 1cm;font-size:10px;color:#888;border-top:1px solid #e5e7eb;background:#fff;text-align:center;}
2812
- </style>
2813
- </head><body>
2814
- <h2>${t}</h2>
2815
- <p>${i.length}행 × ${n.length}열 · ${(/* @__PURE__ */ new Date()).toLocaleString("ko-KR")}</p>
2816
- <table>
2817
- <thead><tr>${o}</tr></thead>
2818
- <tbody>${l}</tbody>
2819
- </table>
2820
- ${r}
2821
- <script>window.addEventListener('load',()=>{window.print();window.addEventListener('afterprint',()=>window.close());});<\/script>
2822
- </body></html>`, c = window.open("", "_blank", "width=960,height=640");
2823
- c && (c.document.write(a), c.document.close());
2824
- }
2825
- exportSheetsExcel(e) {
2826
- const t = this._d.getWsManager();
2827
- if (!t) {
2828
- this.exportExcel(e ?? "workbook");
2829
- return;
2830
- }
2831
- const s = e ?? "workbook.xlsx";
2832
- import("./xlsx.min-Wavxcamn.js").then((i) => i.x).then(({ utils: i, writeFile: n }) => {
2833
- const o = i.book_new(), l = this._d.getOptions();
2834
- for (const r of t.getNames()) {
2835
- const a = t.get(r), c = a.columns.length ? a.columns : l.columns, h = [c.map((g) => g.header)];
2836
- for (const g of a.data)
2837
- h.push(c.map((E) => {
2838
- const b = g[E.field];
2839
- return b == null ? "" : typeof b == "boolean" ? b ? "✓" : "" : E.type === "number" && typeof b == "number" ? b : String(b);
2840
- }));
2841
- const u = i.aoa_to_sheet(h);
2842
- u["!cols"] = c.map(() => ({ wpx: 100 })), i.book_append_sheet(o, u, r);
2843
- }
2844
- n(o, s.endsWith(".xlsx") ? s : s + ".xlsx", { cellStyles: !0 });
2845
- }).catch(() => console.error("exportSheetsExcel: xlsx 패키지를 확인하세요."));
2846
- }
2847
- }
2848
- class zt {
2849
- constructor(e) {
2850
- this._d = e;
2851
- }
2852
- fmtNum(e, t) {
2853
- if (!t)
2854
- return Math.round(e).toLocaleString("ko-KR");
2855
- const s = t.includes("#") || t.includes(","), i = t.match(/\.(\d+)$/), n = i ? parseInt(i[1], 10) : /^\d+$/.test(t) ? parseInt(t, 10) : 0, o = Math.abs(e).toFixed(n), [l = "0", r] = o.split("."), a = s ? l.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : l, c = r !== void 0 ? `${a}.${r}` : a;
2856
- return e < 0 ? `-${c}` : c;
2857
- }
2858
- computeValues() {
2859
- const e = this._d.getOptions().footer;
2860
- if (!e || e.length === 0) return [];
2861
- const t = this._d.getData();
2862
- return e.filter((s) => s.field && s.op).map((s) => {
2863
- const i = s.field, n = s.op, o = t.map((h) => h[i]).filter((h) => h != null && h !== "");
2864
- let l = null;
2865
- const r = n.toUpperCase();
2866
- if (r === "SUM")
2867
- l = o.length > 0 ? x.sum(o.map((h) => String(h))) : null;
2868
- else if (r === "AVG")
2869
- l = o.length > 0 ? x.sum(o.map((h) => String(h))).div(x.from(String(o.length))) : null;
2870
- else if (r === "COUNT") {
2871
- const h = o.length;
2872
- return { _field: i, _value: h, _formatted: h.toLocaleString("ko-KR") };
2873
- } else r === "MAX" ? l = o.length > 0 ? x.max(o.map((h) => String(h))) : null : r === "MIN" && (l = o.length > 0 ? x.min(o.map((h) => String(h))) : null);
2874
- if (!l) return { _field: i, _value: null, _formatted: "" };
2875
- const a = l.toNumber(), c = this.fmtNum(a, s.format);
2876
- return { _field: i, _value: a, _formatted: c };
2877
- });
2878
- }
2879
- render() {
2880
- var h;
2881
- const e = this._d.getContainer(), t = e.querySelector(".og-footer-bar");
2882
- t == null || t.remove();
2883
- const s = this._d.getOptions(), i = s.footer;
2884
- if (!i || i.length === 0) return;
2885
- const n = this._d.getColLayout().visibleLeaves, o = this._d.getColWidths() ?? n.map((u) => u.width ?? 100), l = new Map(
2886
- this.computeValues().map((u) => [u._field, u])
2887
- ), r = document.createElement("div");
2888
- r.className = "og-footer-bar", r.style.cssText = [
2889
- "display:flex;align-items:stretch;",
2890
- `min-height:${s.footerHeight}px;`,
2891
- "border-top:2px solid var(--og-primary,#1976d2);",
2892
- "background:var(--og-header-bg,#f5f5f5);",
2893
- "overflow:hidden;flex-shrink:0;font-size:13px;font-weight:600;"
2894
- ].join("");
2895
- let a = 0;
2896
- if (s.stateColumn && (a += 24), s.draggable && (a += 18), s.rowNumber && (a += 44), s.checkColumn && (a += 36), a > 0) {
2897
- const u = document.createElement("div");
2898
- u.style.cssText = `width:${a}px;flex-shrink:0;border-right:1px solid var(--og-border-color,#e0e0e0);`, r.appendChild(u);
2899
- }
2900
- let c = 0;
2901
- for (const u of i) {
2902
- const g = Math.max(1, u.colspan ?? 1);
2903
- let E = 0;
2904
- for (let y = 0; y < g; y++)
2905
- E += o[c + y] ?? 100;
2906
- const b = n[c];
2907
- c += g;
2908
- const C = document.createElement("div");
2909
- C.style.cssText = [
2910
- `width:${E}px;min-width:${E}px;flex-shrink:0;`,
2911
- "padding:4px 8px;box-sizing:border-box;overflow:hidden;",
2912
- "border-right:1px solid var(--og-border-color,#e0e0e0);",
2913
- "white-space:nowrap;text-overflow:ellipsis;"
2914
- ].join("");
2915
- const M = u.field, _ = M ? l.get(M) : null;
2916
- if (_) {
2917
- const y = _._formatted ?? String(_._value ?? ""), p = u.label ? `${u.label}: ` : "";
2918
- C.textContent = p + y, C.title = `${((h = u.op) == null ? void 0 : h.toUpperCase()) ?? ""} = ${y}`, C.style.color = "var(--og-primary,#1976d2)", C.style.textAlign = u.align ?? ((b == null ? void 0 : b.type) === "number", "right");
2919
- } else u.label && (C.textContent = u.label, C.style.textAlign = u.align ?? "left", C.style.color = "var(--og-row-color,#212121)");
2920
- r.appendChild(C);
2921
- }
2922
- s.footerPosition === "top" ? e.insertBefore(r, e.firstChild) : e.appendChild(r);
2923
- }
2924
- }
2925
- class It {
2926
- constructor(e) {
2927
- this._d = e;
2928
- }
2929
- handleKeyDown(e) {
2930
- const t = this._d.getEditMgr();
2931
- if (t.activeEditor) return;
2932
- this._d.handleCellKeyEvt("cellKeyDown", e);
2933
- const s = this._d.getData(), i = this._d.getColLayout(), n = s.rowCount, o = i.visibleLeaves.length;
2934
- if (n === 0 || o === 0) return;
2935
- if ((e.ctrlKey || e.metaKey) && e.key === "c") {
2936
- e.preventDefault(), this._copyToClipboard();
2937
- return;
2938
- }
2939
- if ((e.ctrlKey || e.metaKey) && e.key === "v") {
2940
- e.preventDefault(), this._pasteFromClipboard();
2941
- return;
2942
- }
2943
- const l = this._d.getOptions();
2944
- if ((e.ctrlKey || e.metaKey) && l.draggable && t.focusCell) {
2945
- if (e.key === "ArrowDown") {
2946
- e.preventDefault();
2947
- const r = t.focusCell.ci !== void 0 ? t.focusCell.ri : 0;
2948
- r < n - 1 && (this._d.handleRowDrop(r, r + 1), this._d.setFocusCell(r + 1, t.focusCell.ci), this._d.announce(`행 ${r + 1}을(를) ${r + 2}번째 위치로 이동`));
2949
- return;
2950
- }
2951
- if (e.key === "ArrowUp") {
2952
- e.preventDefault();
2953
- const r = t.focusCell.ri;
2954
- r > 0 && (this._d.handleRowDrop(r, r - 1), this._d.setFocusCell(r - 1, t.focusCell.ci), this._d.announce(`행 ${r + 1}을(를) ${r}번째 위치로 이동`));
2955
- return;
2956
- }
2957
- }
2958
- switch (e.key) {
2959
- case "ArrowDown": {
2960
- e.preventDefault();
2961
- const r = t.focusCell, a = r ? Math.min(r.ri + 1, n - 1) : 0;
2962
- this._d.setFocusCell(a, (r == null ? void 0 : r.ci) ?? 0);
2963
- break;
2964
- }
2965
- case "ArrowUp": {
2966
- e.preventDefault();
2967
- const r = t.focusCell, a = r ? Math.max(r.ri - 1, 0) : 0;
2968
- this._d.setFocusCell(a, (r == null ? void 0 : r.ci) ?? 0);
2969
- break;
2970
- }
2971
- case "ArrowRight": {
2972
- e.preventDefault();
2973
- const r = t.focusCell;
2974
- if (!r) {
2975
- this._d.setFocusCell(0, 0);
2976
- break;
2977
- }
2978
- r.ci < o - 1 ? this._d.setFocusCell(r.ri, r.ci + 1) : r.ri < n - 1 && this._d.setFocusCell(r.ri + 1, 0);
2979
- break;
2980
- }
2981
- case "ArrowLeft": {
2982
- e.preventDefault();
2983
- const r = t.focusCell;
2984
- if (!r) {
2985
- this._d.setFocusCell(0, 0);
2986
- break;
2987
- }
2988
- r.ci > 0 ? this._d.setFocusCell(r.ri, r.ci - 1) : r.ri > 0 && this._d.setFocusCell(r.ri - 1, o - 1);
2989
- break;
2990
- }
2991
- case "Tab": {
2992
- e.preventDefault();
2993
- const r = t.focusCell;
2994
- if (!r) {
2995
- this._d.setFocusCell(0, 0);
2996
- break;
2997
- }
2998
- e.shiftKey ? r.ci > 0 ? this._d.setFocusCell(r.ri, r.ci - 1) : r.ri > 0 && this._d.setFocusCell(r.ri - 1, o - 1) : r.ci < o - 1 ? this._d.setFocusCell(r.ri, r.ci + 1) : r.ri < n - 1 && this._d.setFocusCell(r.ri + 1, 0);
2999
- break;
3000
- }
3001
- case "Home": {
3002
- if (e.preventDefault(), e.ctrlKey || e.metaKey)
3003
- this._d.setFocusCell(0, 0);
3004
- else {
3005
- const r = t.focusCell;
3006
- this._d.setFocusCell((r == null ? void 0 : r.ri) ?? 0, 0);
3007
- }
3008
- break;
3009
- }
3010
- case "End": {
3011
- if (e.preventDefault(), e.ctrlKey || e.metaKey)
3012
- this._d.setFocusCell(n - 1, o - 1);
3013
- else {
3014
- const r = t.focusCell;
3015
- this._d.setFocusCell((r == null ? void 0 : r.ri) ?? 0, o - 1);
3016
- }
3017
- break;
3018
- }
3019
- case "PageDown": {
3020
- e.preventDefault();
3021
- const r = t.focusCell, a = this._d.getOptions().pageSize ?? 10, c = Math.min(r ? r.ri + a : a - 1, n - 1);
3022
- this._d.setFocusCell(c, (r == null ? void 0 : r.ci) ?? 0);
3023
- break;
3024
- }
3025
- case "PageUp": {
3026
- e.preventDefault();
3027
- const r = t.focusCell, a = this._d.getOptions().pageSize ?? 10, c = r ? Math.max(r.ri - a, 0) : 0;
3028
- this._d.setFocusCell(c, (r == null ? void 0 : r.ci) ?? 0);
3029
- break;
3030
- }
3031
- case " ": {
3032
- if (t.focusCell) {
3033
- e.preventDefault();
3034
- const r = t.focusCell.ri, a = this._d.getRowMgr();
3035
- this._d.getOptions().checkColumn ? (a.check(r, !a.checkedRows.has(r)), this._d.doRender()) : (a.selectToggle(r), this._d.doRender());
3036
- }
3037
- break;
3038
- }
3039
- case "F2":
3040
- case "Enter": {
3041
- t.focusCell && this._d.getOptions().editable && (e.preventDefault(), t.startEditByKey(t.focusCell.ri, t.focusCell.ci));
3042
- break;
3043
- }
3044
- case "Escape": {
3045
- t.clearFocusCell(), this._d.doRender();
3046
- break;
3047
- }
3048
- }
3049
- }
3050
- _copyToClipboard() {
3051
- var o;
3052
- if (!this._d.getOptions().clipboard) return;
3053
- const t = this._d.getEditMgr(), s = this._d.getColLayout(), i = this._d.getData();
3054
- let n = "";
3055
- if (t.focusCell) {
3056
- const { ri: l, ci: r } = t.focusCell, a = s.visibleLeaves[r];
3057
- a && (n = String(i.getCellValue(l, a.field) ?? ""));
3058
- } else if (this._d.getRowMgr().selectedRows.size > 0) {
3059
- const l = s.visibleLeaves;
3060
- n = [...this._d.getRowMgr().selectedRows].sort((a, c) => a - c).map((a) => {
3061
- const c = i.getRowByIndex(a);
3062
- return l.map((h) => String((c == null ? void 0 : c[h.field]) ?? "")).join(" ");
3063
- }).join(`
3064
- `);
3065
- }
3066
- n && ((o = navigator.clipboard) == null || o.writeText(n).catch(() => {
3067
- }));
3068
- }
3069
- _pasteFromClipboard() {
3070
- var s;
3071
- const e = this._d.getOptions();
3072
- if (!e.clipboard || !e.editable) return;
3073
- const t = this._d.getEditMgr();
3074
- t.focusCell && ((s = navigator.clipboard) == null || s.readText().then((i) => {
3075
- if (!i) return;
3076
- const { ri: n, ci: o } = t.focusCell, l = i.split(`
3077
- `), r = this._d.getColLayout().visibleLeaves, a = this._d.getData();
3078
- for (let c = 0; c < l.length; c++) {
3079
- const h = l[c].split(" ");
3080
- for (let u = 0; u < h.length; u++) {
3081
- const g = n + c, E = o + u, b = r[E];
3082
- b && g < a.rowCount && a.updateCell(g, b.field, h[u]);
3083
- }
3084
- }
3085
- this._d.emit("dataChange", a.getData()), this._d.doRender();
3086
- }).catch(() => {
3087
- }));
3088
- }
3089
- }
3090
- class Ht {
3091
- constructor(e) {
3092
- this._bar = null, this._input = null, this._count = null, this._filter = "", this._d = e;
3093
- }
3094
- get findFilter() {
3095
- return this._filter;
3096
- }
3097
- init(e) {
3098
- const t = document.createElement("div");
3099
- t.className = "og-find-bar", t.hidden = !0;
3100
- const s = document.createElement("span");
3101
- s.className = "og-find-label", s.textContent = "찾기";
3102
- const i = document.createElement("input");
3103
- i.type = "text", i.className = "og-find-input", i.placeholder = "검색어 입력...", i.setAttribute("aria-label", "그리드 내 검색");
3104
- const n = document.createElement("span");
3105
- n.className = "og-find-count";
3106
- const o = document.createElement("button");
3107
- o.className = "og-find-close", o.textContent = "✕", o.setAttribute("aria-label", "찾기 닫기"), t.appendChild(s), t.appendChild(i), t.appendChild(n), t.appendChild(o), e.insertBefore(t, e.firstChild), i.addEventListener("input", () => {
3108
- this._filter = i.value.trim(), this._apply();
3109
- }), i.addEventListener("keydown", (l) => {
3110
- l.key === "Escape" && this.close();
3111
- }), o.addEventListener("click", () => this.close()), this._bar = t, this._input = i, this._count = n;
3112
- }
3113
- open() {
3114
- this._bar && (this._bar.hidden = !1, this._input.focus(), this._input.select());
3115
- }
3116
- close() {
3117
- this._bar && (this._bar.hidden = !0, this._filter = "", this._input.value = "", this._count && (this._count.textContent = ""), this._apply());
3118
- }
3119
- _apply() {
3120
- var i, n;
3121
- const e = this._d.getData(), t = this._d.getColLayout().visibleLeaves.map((o) => o.field);
3122
- e.setFindFilter(this._filter, t), e.applyFilter(this._d.getFilters());
3123
- const s = e.rowCount;
3124
- (i = this._d.getVs()) == null || i.setTotalRows(s), (n = this._d.getPagination()) == null || n.setTotalRows(s), this._count && (this._count.textContent = this._filter ? `${s}건` : ""), this._d.doRender();
3125
- }
3126
- }
3127
- function Ke(d) {
3128
- return d && d._isGroup === !0;
3129
- }
3130
- function Ie(d, e, t = [], s = /* @__PURE__ */ new Set(), i) {
3131
- return e.length ? Oe(d, e, 0, t, s, "", i) : [];
3132
- }
3133
- function Oe(d, e, t, s, i, n, o) {
3134
- const l = e[t], r = /* @__PURE__ */ new Map();
3135
- for (const c of d) {
3136
- const h = c[l];
3137
- r.has(h) || r.set(h, []), r.get(h).push(c);
3138
- }
3139
- const a = [];
3140
- for (const [c, h] of r) {
3141
- const u = `${n}__${l}:${c}`, g = i.has(u);
3142
- let E;
3143
- t < e.length - 1 ? E = Oe(h, e, t + 1, s, i, u, o) : E = h;
3144
- const { summary: b, summaryFmt: C } = Bt(h, s), M = Wt(h, o);
3145
- a.push({
3146
- _isGroup: !0,
3147
- _groupField: l,
3148
- _groupValue: c,
3149
- _groupLabel: c == null ? "(없음)" : String(c),
3150
- _depth: t,
3151
- _expanded: g,
3152
- _childCount: h.length,
3153
- _summary: b,
3154
- _summaryFmt: C,
3155
- _states: M,
3156
- children: E
3157
- });
3158
- }
3159
- return a;
3160
- }
3161
- function Bt(d, e) {
3162
- const t = {}, s = {};
3163
- for (const i of e) {
3164
- const n = d.map((a) => a[i.field]).filter((a) => a != null && a !== "");
3165
- let o = null;
3166
- const l = i.op.toUpperCase();
3167
- if (l === "SUM")
3168
- o = n.length > 0 ? x.sum(n.map(String)) : null;
3169
- else if (l === "AVG")
3170
- o = n.length > 0 ? x.sum(n.map(String)).div(x.from(String(n.length))) : null;
3171
- else if (l === "COUNT") {
3172
- t[i.field] = d.length, s[i.field] = d.length.toLocaleString("ko-KR");
3173
- continue;
3174
- } else l === "MAX" ? o = n.length > 0 ? x.max(n.map(String)) : null : l === "MIN" && (o = n.length > 0 ? x.min(n.map(String)) : null);
3175
- if (!o) {
3176
- t[i.field] = null, s[i.field] = "";
3177
- continue;
3178
- }
3179
- const r = o.toNumber();
3180
- t[i.field] = r, s[i.field] = Nt(r, i.format);
3181
- }
3182
- return { summary: t, summaryFmt: s };
3183
- }
3184
- function Wt(d, e) {
3185
- if (!e) return { added: 0, edited: 0, removed: 0 };
3186
- let t = 0, s = 0, i = 0;
3187
- for (const n of d) {
3188
- const o = e(n);
3189
- o === "added" ? t++ : o === "edited" ? s++ : o === "removed" && i++;
3190
- }
3191
- return { added: t, edited: s, removed: i };
3192
- }
3193
- function Nt(d, e) {
3194
- if (e == null)
3195
- return d % 1 === 0 ? d.toLocaleString("ko-KR") : parseFloat(d.toFixed(6)).toLocaleString("ko-KR", {
3196
- minimumFractionDigits: 2,
3197
- maximumFractionDigits: 6
3198
- });
3199
- const t = e.includes("#") || e.includes(","), s = e.match(/\.(\d+)$/), i = s ? parseInt(s[1], 10) : /^\d+$/.test(e) ? parseInt(e, 10) : 0, n = Math.abs(d).toFixed(i), [o = "0", l] = n.split("."), r = t ? o.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : o, a = l !== void 0 ? `${r}.${l}` : r;
3200
- return d < 0 ? `-${a}` : a;
3201
- }
3202
- function Ve(d) {
3203
- const e = [];
3204
- for (const t of d)
3205
- if (e.push(t), t._expanded)
3206
- for (const s of t.children)
3207
- Ke(s) ? e.push(...Ve([s])) : e.push(s);
3208
- return e;
3209
- }
3210
- function Pe(d, e = "") {
3211
- const t = [];
3212
- for (const s of d) {
3213
- const i = `${e}__${s._groupField}:${s._groupValue}`;
3214
- t.push(i);
3215
- const n = s.children.filter((o) => Ke(o));
3216
- n.length && t.push(...Pe(n, i));
3217
- }
3218
- return t;
3219
- }
3220
- function He(d, e, t = /* @__PURE__ */ new Set()) {
3221
- const { idField: s, parentIdField: i, expandOnLoad: n = !1 } = e, o = /* @__PURE__ */ new Map(), l = [];
3222
- for (const c of d) {
3223
- const h = c[s], u = {
3224
- _isTree: !0,
3225
- _treeId: h,
3226
- _treeParentId: c[i],
3227
- _depth: 0,
3228
- _expanded: n || t.has(h),
3229
- _hasChildren: !1,
3230
- _childCount: 0,
3231
- _isLastChild: !1,
3232
- _ancestorHasMore: [],
3233
- data: c,
3234
- children: []
3235
- };
3236
- o.set(h, u);
3237
- }
3238
- for (const c of o.values()) {
3239
- const h = c._treeParentId;
3240
- if (h == null || h === "" || !o.has(h))
3241
- l.push(c);
3242
- else {
3243
- const g = o.get(h);
3244
- g.children.push(c), g._hasChildren = !0;
3245
- }
3246
- }
3247
- function r(c, h) {
3248
- for (const u of c)
3249
- u._depth = h, u._childCount = Ue(u), r(u.children, h + 1);
3250
- }
3251
- r(l, 0);
3252
- function a(c, h) {
3253
- for (let u = 0; u < c.length; u++) {
3254
- const g = c[u], E = u === c.length - 1;
3255
- g._isLastChild = E, g._ancestorHasMore = h, g.children.length > 0 && a(g.children, [...h, !E]);
3256
- }
3257
- }
3258
- return a(l, []), l;
3259
- }
3260
- function Ue(d) {
3261
- let e = d.children.length;
3262
- for (const t of d.children) e += Ue(t);
3263
- return e;
3264
- }
3265
- function je(d) {
3266
- const e = [];
3267
- for (const t of d)
3268
- e.push(t), t._expanded && t.children.length > 0 && e.push(...je(t.children));
3269
- return e;
3270
- }
3271
- function Kt(d, e) {
3272
- d.has(e) ? d.delete(e) : d.add(e);
3273
- }
3274
- function xe(d) {
3275
- const e = [];
3276
- for (const t of d)
3277
- e.push(t._treeId), t.children.length && e.push(...xe(t.children));
3278
- return e;
3279
- }
3280
- class Ot {
3281
- constructor(e) {
3282
- this._groupFields = [], this._groupExpandedKeys = /* @__PURE__ */ new Set(), this._groupFlatRows = [], this._isGroupMode = !1, this._treeRoots = [], this._treeFlatRows = [], this._treeExpandedKeys = /* @__PURE__ */ new Set(), this._isTreeMode = !1, this._d = e;
3283
- }
3284
- // ─── 상태 접근자 ─────────────────────────────────────────
3285
- get isGroupMode() {
3286
- return this._isGroupMode;
3287
- }
3288
- get isTreeMode() {
3289
- return this._isTreeMode;
3290
- }
3291
- get groupFlatRows() {
3292
- return this._groupFlatRows;
3293
- }
3294
- get treeFlatRows() {
3295
- return this._treeFlatRows;
3296
- }
3297
- // ─── 그룹 ─────────────────────────────────────────────────
3298
- groupBy(e) {
3299
- this._groupFields = e, this._groupExpandedKeys.clear(), this._isGroupMode = e.length > 0, this.rebuildGroups();
3300
- }
3301
- clearGroup() {
3302
- var t;
3303
- this._groupFields = [], this._groupExpandedKeys.clear(), this._isGroupMode = !1, this._groupFlatRows = [];
3304
- const e = this._d.getData().length;
3305
- (t = this._d.getVs()) == null || t.setTotalRows(e), this._d.doRender();
3306
- }
3307
- expandAll() {
3308
- if (!this._isGroupMode) return;
3309
- const e = Ie(this._d.getData(), this._groupFields, this._getSummaryDefs());
3310
- Pe(e).forEach((t) => this._groupExpandedKeys.add(t)), this.rebuildGroups();
3311
- }
3312
- collapseAll() {
3313
- this._groupExpandedKeys.clear(), this._isGroupMode && this.rebuildGroups();
3314
- }
3315
- handleGroupToggle(e) {
3316
- this._groupExpandedKeys.has(e) ? this._groupExpandedKeys.delete(e) : this._groupExpandedKeys.add(e), this.rebuildGroups();
3317
- }
3318
- rebuildGroups() {
3319
- var n;
3320
- const e = this._d.getData(), t = this._d.getDataLayer(), s = (o) => {
3321
- const l = e.indexOf(o);
3322
- return l >= 0 ? t.getRowState(l) : "none";
3323
- }, i = Ie(e, this._groupFields, this._getSummaryDefs(), this._groupExpandedKeys, s);
3324
- this._groupFlatRows = Ve(i), (n = this._d.getVs()) == null || n.setTotalRows(this._groupFlatRows.length), this._d.doRenderFull(this._groupFlatRows.length);
3325
- }
3326
- // ─── 트리 ─────────────────────────────────────────────────
3327
- enableTree() {
3328
- this._isTreeMode = !0, this._isGroupMode = !1;
3329
- const e = this._d.getOptions();
3330
- if (e.expandOnLoad) {
3331
- const t = He(this._d.getData(), {
3332
- idField: e.treeId,
3333
- parentIdField: e.treeParentId
3334
- });
3335
- xe(t).forEach((s) => this._treeExpandedKeys.add(s));
3336
- }
3337
- this.rebuildTree();
3338
- }
3339
- disableTree() {
3340
- var t;
3341
- this._isTreeMode = !1, this._treeRoots = [], this._treeFlatRows = [], this._treeExpandedKeys.clear();
3342
- const e = this._d.getData().length;
3343
- (t = this._d.getVs()) == null || t.setTotalRows(e), this._d.doRender();
3344
- }
3345
- expandNodes(e, t = !0) {
3346
- const s = Array.isArray(e) ? e : [e];
3347
- for (const i of s)
3348
- t ? this._treeExpandedKeys.add(i) : this._treeExpandedKeys.delete(i);
3349
- this._isTreeMode && this.rebuildTree();
3350
- }
3351
- expandAllNodes() {
3352
- this._isTreeMode && (xe(this._treeRoots).forEach((e) => this._treeExpandedKeys.add(e)), this.rebuildTree());
3353
- }
3354
- collapseAllNodes() {
3355
- this._isTreeMode && (this._treeExpandedKeys.clear(), this.rebuildTree());
3356
- }
3357
- handleTreeToggle(e) {
3358
- Kt(this._treeExpandedKeys, e), this.rebuildTree();
3359
- }
3360
- rebuildTree() {
3361
- var t;
3362
- const e = this._d.getOptions();
3363
- this._treeRoots = He(this._d.getData(), {
3364
- idField: e.treeId,
3365
- parentIdField: e.treeParentId,
3366
- expandOnLoad: e.expandOnLoad
3367
- }, this._treeExpandedKeys), this._treeFlatRows = je(this._treeRoots), (t = this._d.getVs()) == null || t.setTotalRows(this._treeFlatRows.length), this._d.doRenderFull(this._treeFlatRows.length);
3368
- }
3369
- // ─── 내부 헬퍼 ───────────────────────────────────────────
3370
- _getSummaryDefs() {
3371
- const e = this._d.getOptions().summary;
3372
- if (!e) return [];
3373
- if (e.rows && e.rows.length > 0)
3374
- return e.fields.flatMap(
3375
- (s) => e.rows.map((i) => ({ field: s, op: i.op, format: i.format }))
3376
- );
3377
- const t = Array.isArray(e.ops) ? e.ops : e.ops ? [e.ops] : ["SUM"];
3378
- return e.fields.map((s) => ({ field: s, op: t[0] ?? "SUM", format: e.format }));
3379
- }
3380
- }
3381
- class Vt {
3382
- constructor(e) {
3383
- this._sortList = [], this._filters = {}, this._d = e;
3384
- }
3385
- // ─── 상태 접근자 ─────────────────────────────────────────
3386
- get sortList() {
3387
- return this._sortList;
3388
- }
3389
- get filters() {
3390
- return this._filters;
3391
- }
3392
- // ─── 정렬 ─────────────────────────────────────────────────
3393
- handleSortClick(e, t) {
3394
- var l;
3395
- const s = this._d.getOptions();
3396
- if (!s.sortable) return;
3397
- const i = this._sortList.findIndex((r) => r.field === e);
3398
- if (i >= 0) {
3399
- const r = this._sortList[i];
3400
- r.dir === "asc" ? r.dir = "desc" : this._sortList.splice(i, 1);
3401
- } else
3402
- (!t || !s.multiSort) && (this._sortList = []), this._sortList.push({ field: e, dir: "asc" });
3403
- this._d.getData().applySort(this._sortList), this._d.renderHeader(), this._d.doRender();
3404
- const n = this._sortList.find((r) => r.field === e), o = n ? n.dir === "asc" ? "오름차순" : "내림차순" : "정렬 해제";
3405
- this._d.announce(`${e} ${o} 정렬`), this._d.emit("sortChange", { sortList: this._sortList }), (l = s.onSortChange) == null || l.call(s, { field: e, dir: (n == null ? void 0 : n.dir) ?? "asc", sortList: this._sortList });
3406
- }
3407
- sort(e, t = "asc") {
3408
- if (Array.isArray(e))
3409
- this._sortList = e;
3410
- else {
3411
- const s = this._sortList.findIndex((i) => i.field === e);
3412
- s >= 0 ? this._sortList[s].dir = t : this._sortList = [{ field: e, dir: t }], this._d.getOptions().multiSort || (this._sortList = this._sortList.slice(-1));
3413
- }
3414
- this._d.getData().applySort(this._sortList), this._d.renderHeader(), this._d.doRender(), this._d.emit("sortChange", { sortList: this._sortList });
3415
- }
3416
- resetSort() {
3417
- this._sortList = [], this._d.getData().applySort([]), this._d.renderHeader(), this._d.doRender();
3418
- }
3419
- initSort(e) {
3420
- this._sortList = [...e], this._d.getData().applySort(this._sortList);
3421
- }
3422
- getSortState() {
3423
- return [...this._sortList];
3424
- }
3425
- // ─── 필터 ─────────────────────────────────────────────────
3426
- setFilter(e, t) {
3427
- var s, i;
3428
- this._filters[e] = t, this.applyFilters(), this._d.renderHeader(), this._d.doRender(), this._d.emit("filterChange", { field: e, filterItems: t, allFilters: this._filters }), (i = (s = this._d.getOptions()).onFilterChange) == null || i.call(s, { field: e, filterItems: t, allFilters: this._filters });
3429
- }
3430
- resetFilter(e) {
3431
- e ? delete this._filters[e] : this._filters = {}, this.applyFilters(), this._d.renderHeader(), this._d.doRender();
3432
- }
3433
- getFilterState() {
3434
- return { ...this._filters };
3435
- }
3436
- restoreFilter(e) {
3437
- this._filters = { ...e }, this.applyFilters();
3438
- }
3439
- applyFilters() {
3440
- var s, i;
3441
- const e = this._d.getData();
3442
- e.setFindFilter(this._d.getFindFilter(), this._d.getColLayout().visibleLeaves.map((n) => n.field)), e.applyFilter(this._filters);
3443
- const t = e.rowCount;
3444
- (s = this._d.getVs()) == null || s.setTotalRows(t), (i = this._d.getPagination()) == null || i.setTotalRows(t);
3445
- }
3446
- }
3447
- class Pt {
3448
- constructor(e) {
3449
- this._d = e;
3450
- }
3451
- handleCellClick(e, t, s) {
3452
- var a, c, h, u, g, E, b;
3453
- const i = this._d.getOptions(), n = this._d.getRowMgr(), o = this._d.getEditMgr();
3454
- i.selection === "single" || i.selection === "row" ? n.selectSingle(e) : i.selection === "multiple" && (s.ctrlKey || s.metaKey ? n.selectToggle(e) : n.selectSingle(e));
3455
- const l = this._d.getData().getRowByIndex(e), r = this._d.getColLayout().visibleLeaves[t];
3456
- if (l && r) {
3457
- const C = r.editable !== !1 && (r.editable !== void 0 || i.editable);
3458
- if (ee(r) && C) {
3459
- const T = l[r.field];
3460
- this._d.writeCell(e, r.field, !T);
3461
- }
3462
- if (r.type === "radio") {
3463
- const T = r.group;
3464
- for (const F of this._d.getColLayout().visibleLeaves)
3465
- F.type === "radio" && F.field !== r.field && (!T || F.group === T) && this._d.getData().updateCell(e, F.field, !1);
3466
- this._d.writeCell(e, r.field, !0);
3467
- }
3468
- let M = l[r.field];
3469
- if (M === void 0 && r.formula)
3470
- try {
3471
- const T = r.formulaPrecision ?? 30, F = Be(r.formula, l, T);
3472
- M = F instanceof x ? r.precision != null ? F.toFixed(r.precision) : F.toString() : String(F);
3473
- } catch {
3474
- }
3475
- const _ = {
3476
- type: "cellClick",
3477
- rowIndex: e,
3478
- columnIndex: t,
3479
- field: r.field,
3480
- value: M,
3481
- row: l,
3482
- column: r,
3483
- target: s.target,
3484
- originalEvent: s
3485
- };
3486
- this._d.emit("cellClick", _), (a = i.onCellClick) == null || a.call(i, _);
3487
- const y = { type: "rowClick", rowIndex: e, row: l, target: s.target, originalEvent: s };
3488
- this._d.emit("rowClick", y), (c = i.onRowClick) == null || c.call(i, y);
3489
- const p = r.type === "select";
3490
- !(o.activeEditor != null && ((h = o.editCell) == null ? void 0 : h.ri) === e && ((u = o.editCell) == null ? void 0 : u.ci) === t) && (i.editMode === "click" || p) && !ee(r) && o.startEdit(e, t, s);
3491
- }
3492
- o.activeEditor && ((g = o.editCell) == null ? void 0 : g.ri) === e && ((E = o.editCell) == null ? void 0 : E.ci) === t || (this._d.doRender(), this._d.emit("selectionChange", {
3493
- rows: n.getSelections(),
3494
- rowIndexes: [...n.selectedRows]
3495
- }), (b = i.onSelectionChange) == null || b.call(i, { rows: n.getSelections(), rowIndexes: [...n.selectedRows], cells: [] }));
3496
- }
3497
- handleCellDblClick(e, t, s) {
3498
- var a, c;
3499
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3500
- if (!i || !n) return;
3501
- const o = this._d.getOptions(), l = {
3502
- type: "cellDblClick",
3503
- rowIndex: e,
3504
- columnIndex: t,
3505
- field: n.field,
3506
- value: i[n.field],
3507
- row: i,
3508
- column: n,
3509
- target: s.target,
3510
- originalEvent: s
3511
- };
3512
- this._d.emit("cellDblClick", l), (a = o.onCellDblClick) == null || a.call(o, l);
3513
- const r = { type: "rowDblClick", rowIndex: e, row: i, target: s.target, originalEvent: s };
3514
- this._d.emit("rowDblClick", r), (c = o.onRowDblClick) == null || c.call(o, r), o.editMode === "dblclick" && this._d.getEditMgr().startEdit(e, t, s);
3515
- }
3516
- handleCellMouseOver(e, t, s) {
3517
- var a, c;
3518
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3519
- if (!i || !n) return;
3520
- const o = this._d.getOptions(), l = { type: "cellMouseOver", rowIndex: e, columnIndex: t, field: n.field, value: i[n.field], row: i, column: n, target: s.target, originalEvent: s };
3521
- this._d.emit("cellMouseOver", l), (a = o.onCellMouseOver) == null || a.call(o, l);
3522
- const r = { type: "rowMouseOver", rowIndex: e, row: i, target: s.target, originalEvent: s };
3523
- this._d.emit("rowMouseOver", r), (c = o.onRowMouseOver) == null || c.call(o, r);
3524
- }
3525
- handleCellMouseOut(e, t, s) {
3526
- var a, c;
3527
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3528
- if (!i || !n) return;
3529
- const o = this._d.getOptions(), l = { type: "cellMouseOut", rowIndex: e, columnIndex: t, field: n.field, value: i[n.field], row: i, column: n, target: s.target, originalEvent: s };
3530
- this._d.emit("cellMouseOut", l), (a = o.onCellMouseOut) == null || a.call(o, l);
3531
- const r = { type: "rowMouseOut", rowIndex: e, row: i, target: s.target, originalEvent: s };
3532
- this._d.emit("rowMouseOut", r), (c = o.onRowMouseOut) == null || c.call(o, r);
3533
- }
3534
- handleCellMouseDown(e, t, s) {
3535
- var a, c;
3536
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3537
- if (!i || !n) return;
3538
- const o = this._d.getOptions(), l = { type: "cellMouseDown", rowIndex: e, columnIndex: t, field: n.field, value: i[n.field], row: i, column: n, target: s.target, originalEvent: s };
3539
- this._d.emit("cellMouseDown", l), (a = o.onCellMouseDown) == null || a.call(o, l);
3540
- const r = { type: "rowMouseDown", rowIndex: e, row: i, target: s.target, originalEvent: s };
3541
- this._d.emit("rowMouseDown", r), (c = o.onRowMouseDown) == null || c.call(o, r);
3542
- }
3543
- handleCellMouseUp(e, t, s) {
3544
- var a, c;
3545
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3546
- if (!i || !n) return;
3547
- const o = this._d.getOptions(), l = { type: "cellMouseUp", rowIndex: e, columnIndex: t, field: n.field, value: i[n.field], row: i, column: n, target: s.target, originalEvent: s };
3548
- this._d.emit("cellMouseUp", l), (a = o.onCellMouseUp) == null || a.call(o, l);
3549
- const r = { type: "rowMouseUp", rowIndex: e, row: i, target: s.target, originalEvent: s };
3550
- this._d.emit("rowMouseUp", r), (c = o.onRowMouseUp) == null || c.call(o, r);
3551
- }
3552
- handleCellMouseMove(e, t, s) {
3553
- var a, c;
3554
- const i = this._d.getData().getRowByIndex(e), n = this._d.getColLayout().visibleLeaves[t];
3555
- if (!i || !n) return;
3556
- const o = this._d.getOptions(), l = { type: "cellMouseMove", rowIndex: e, columnIndex: t, field: n.field, value: i[n.field], row: i, column: n, target: s.target, originalEvent: s };
3557
- this._d.emit("cellMouseMove", l), (a = o.onCellMouseMove) == null || a.call(o, l);
3558
- const r = { type: "rowMouseMove", rowIndex: e, row: i, target: s.target, originalEvent: s };
3559
- this._d.emit("rowMouseMove", r), (c = o.onRowMouseMove) == null || c.call(o, r);
3560
- }
3561
- handleCellKeyEvt(e, t) {
3562
- var c, h, u;
3563
- const s = this._d.getEditMgr();
3564
- if (!s.focusCell || s.activeEditor) return;
3565
- const { ri: i, ci: n } = s.focusCell, o = this._d.getData().getRowByIndex(i), l = this._d.getColLayout().visibleLeaves[n];
3566
- if (!o || !l) return;
3567
- const r = this._d.getOptions(), a = { type: e, rowIndex: i, columnIndex: n, field: l.field, value: o[l.field], row: o, column: l, key: t.key, target: this._d.getContainer(), originalEvent: t };
3568
- this._d.emit(e, a), e === "cellKeyDown" ? (c = r.onCellKeyDown) == null || c.call(r, a) : e === "cellKeyUp" ? (h = r.onCellKeyUp) == null || h.call(r, a) : (u = r.onCellKeyPress) == null || u.call(r, a);
3569
- }
3570
- }
3571
- class Ut {
3572
- constructor() {
3573
- this._triggers = /* @__PURE__ */ new Map();
3574
- }
3575
- add(e, t) {
3576
- this._triggers.has(e) || this._triggers.set(e, []), this._triggers.get(e).push(t);
3577
- }
3578
- remove(e, t) {
3579
- const s = this._triggers.get(e);
3580
- if (s) {
3581
- const i = s.indexOf(t);
3582
- i >= 0 && s.splice(i, 1);
3583
- }
3584
- }
3585
- clear(e) {
3586
- e ? this._triggers.delete(e) : this._triggers.clear();
3587
- }
3588
- mkCtx(e, t) {
3589
- let s = !1;
3590
- return {
3591
- operation: e,
3592
- args: t,
3593
- result: void 0,
3594
- extra: {},
3595
- timestamp: Date.now(),
3596
- get cancelled() {
3597
- return s;
3598
- },
3599
- cancel() {
3600
- s = !0;
3601
- }
3602
- };
3603
- }
3604
- exec(e, t) {
3605
- const s = this._triggers.get(e) ?? [];
3606
- for (const i of s)
3607
- if (i(t), t.cancelled) return !1;
3608
- if (e.startsWith("after:")) {
3609
- const i = this._triggers.get("complete") ?? [];
3610
- for (const n of i) n(t);
3611
- }
3612
- return !0;
3613
- }
3614
- }
3615
- const jt = "_ogRowId";
3616
- class Xt extends Ye {
3617
- constructor(e, t) {
3618
- var i;
3619
- super(), this._vs = null, this._ro = null, this._renderer = null, this._trigMgr = new Ut(), this._destroyed = !1, this._colWidths = [], this._filterPanel = null, this._filterSelect = null, this._pagination = null, this._dnd = null, this._mergeEngine = new Q(), this._liveRegion = null, this._ctxMenu = null, this._cmHandler = null, this._cmKbdHandler = null, this._wsManager = null;
3620
- const s = typeof e == "string" ? document.querySelector(e) : e;
3621
- if (!s) throw new Error(`OpenGrid: container not found: ${e}`);
3622
- this._container = s, this._options = {
3623
- height: "100%",
3624
- width: "100%",
3625
- rowHeight: 32,
3626
- headerHeight: 34,
3627
- footerHeight: 30,
3628
- autoHeight: !1,
3629
- fillWidth: !1,
3630
- defaultColumnWidth: 100,
3631
- editable: !1,
3632
- editMode: "dblclick",
3633
- history: !0,
3634
- historySize: 100,
3635
- selection: "single",
3636
- clipboard: !0,
3637
- sortable: !0,
3638
- multiSort: !0,
3639
- filterable: !0,
3640
- defaultSort: [],
3641
- frozenColumns: 0,
3642
- frozenRows: 0,
3643
- rowNumber: !1,
3644
- stateColumn: !1,
3645
- checkColumn: !1,
3646
- draggable: !1,
3647
- mergeCells: !1,
3648
- groupBy: [],
3649
- summary: void 0,
3650
- treeMode: "auto",
3651
- treeId: "id",
3652
- treeParentId: "parentId",
3653
- expandOnLoad: !1,
3654
- pagination: !1,
3655
- pageSize: 50,
3656
- footer: void 0,
3657
- footerPosition: "bottom",
3658
- theme: "default",
3659
- cssVars: {},
3660
- ariaLabel: "OPEN_GRID 데이터 그리드",
3661
- ...t
3662
- }, this._data = new Ge(jt), this._rowMgr = new kt(this._data), this._colLayout = new le(this._options.columns, this._options.frozenColumns), this._editMgr = new Et({
3663
- data: this._data,
3664
- colLayout: this._colLayout,
3665
- getRenderer: () => this._renderer,
3666
- getContainer: () => this._container,
3667
- getOptions: () => this._options,
3668
- emit: (n, ...o) => this.emit(n, ...o),
3669
- doRender: () => this._doRender(...this._visRange()),
3670
- announce: (n) => this._announce(n),
3671
- writeCell: (n, o, l) => this.writeCell(n, o, l),
3672
- scrollToRow: (n) => {
3673
- var o;
3674
- return (o = this._vs) == null ? void 0 : o.scrollToRow(n);
3675
- },
3676
- getVisibleLeaves: () => this._colLayout.visibleLeaves
3677
- }), this._exportMgr = new At({
3678
- getData: () => this._data.getData(),
3679
- getColLayout: () => this._colLayout,
3680
- getColWidths: () => this._colWidths,
3681
- getOptions: () => this._options,
3682
- getContainer: () => this._container,
3683
- getMaskEnabled: (n) => this.getMaskEnabled(n),
3684
- getWsManager: () => this._wsManager
3685
- }), this._footerMgr = new zt({
3686
- getData: () => this._data.getData(),
3687
- getColLayout: () => this._colLayout,
3688
- getColWidths: () => this._colWidths,
3689
- getOptions: () => this._options,
3690
- getContainer: () => this._container
3691
- }), this._kbdMgr = new It({
3692
- getEditMgr: () => this._editMgr,
3693
- getRowMgr: () => this._rowMgr,
3694
- getData: () => this._data,
3695
- getColLayout: () => this._colLayout,
3696
- getOptions: () => this._options,
3697
- setFocusCell: (n, o) => this._setFocusCell(n, o),
3698
- handleRowDrop: (n, o) => this._handleRowDrop(n, o),
3699
- doRender: () => this._doRender(...this._visRange()),
3700
- announce: (n) => this._announce(n),
3701
- emit: (n, ...o) => this.emit(n, ...o),
3702
- visRange: () => this._visRange(),
3703
- handleCellKeyEvt: (n, o) => this._handleCellKeyEvt(n, o)
3704
- }), this._sfMgr = new Vt({
3705
- getData: () => this._data,
3706
- getColLayout: () => this._colLayout,
3707
- getFindFilter: () => this._findMgr.findFilter,
3708
- getVs: () => this._vs,
3709
- getPagination: () => this._pagination,
3710
- getOptions: () => this._options,
3711
- renderHeader: () => this._renderHeader(),
3712
- doRender: () => this._doRender(...this._visRange()),
3713
- announce: (n) => this._announce(n),
3714
- emit: (n, ...o) => this.emit(n, ...o)
3715
- }), this._findMgr = new Ht({
3716
- getColLayout: () => this._colLayout,
3717
- getData: () => this._data,
3718
- getFilters: () => this._sfMgr.filters,
3719
- getVs: () => this._vs,
3720
- getPagination: () => this._pagination,
3721
- doRender: () => this._doRender(...this._visRange())
3722
- }), this._cellEvt = new Pt({
3723
- getData: () => this._data,
3724
- getColLayout: () => this._colLayout,
3725
- getOptions: () => this._options,
3726
- getEditMgr: () => this._editMgr,
3727
- getRowMgr: () => this._rowMgr,
3728
- emit: (n, ...o) => this.emit(n, ...o),
3729
- writeCell: (n, o, l) => this.writeCell(n, o, l),
3730
- doRender: () => this._doRender(...this._visRange()),
3731
- getContainer: () => this._container
3732
- }), this._grpMgr = new Ot({
3733
- getData: () => this._data.getData(),
3734
- getDataLayer: () => this._data,
3735
- getOptions: () => this._options,
3736
- getVs: () => this._vs,
3737
- doRenderFull: (n) => this._doRender(0, n - 1),
3738
- doRender: () => this._doRender(...this._visRange())
3739
- }), this._mount(), this._bindOptionEvents(), (i = this._options.defaultSort) != null && i.length && this._sfMgr.initSort(this._options.defaultSort), requestAnimationFrame(() => {
3740
- var n, o;
3741
- this.emit("ready", this), (o = (n = this._options).onReady) == null || o.call(n, this);
3742
- });
3743
- }
3744
- _mount() {
3745
- var s, i;
3746
- this._container.classList.add("og-container");
3747
- const e = this._options.height, t = this._options.width;
3748
- this._container.style.height = typeof e == "number" ? `${e}px` : String(e), this._container.style.width = typeof t == "number" ? `${t}px` : String(t), this._container.style.display = "flex", this._container.style.flexDirection = "column", this._container.style.overflow = "hidden", this._container.style.boxSizing = "border-box", this._container.style.border = "1px solid var(--og-border-color, #e0e0e0)", this._container.style.fontFamily = "var(--og-font-family, -apple-system, sans-serif)", this._container.style.fontSize = "var(--og-font-size, 13px)", this._container.setAttribute("data-og-theme", this._options.theme);
3749
- for (const [n, o] of Object.entries(this._options.cssVars))
3750
- this._container.style.setProperty(n, o);
3751
- this._renderer = new Mt(this._container, this._options, {
3752
- onHeaderClick: (n, o) => this._handleSortClick(n, o),
3753
- onCellClick: (n, o, l) => this._handleCellClick(n, o, l),
3754
- onCellDblClick: (n, o, l) => this._handleCellDblClick(n, o, l),
3755
- onCellMouseOver: (n, o, l) => this._handleCellMouseOver(n, o, l),
3756
- onCellMouseOut: (n, o, l) => this._handleCellMouseOut(n, o, l),
3757
- onCellMouseDown: (n, o, l) => this._handleCellMouseDown(n, o, l),
3758
- onCellMouseUp: (n, o, l) => this._handleCellMouseUp(n, o, l),
3759
- onCellMouseMove: (n, o, l) => this._handleCellMouseMove(n, o, l),
3760
- onRowCheck: (n, o) => this._handleRowCheck(n, o),
3761
- onAllCheck: (n) => this._handleAllCheck(n),
3762
- onColResize: (n, o) => this._handleColResize(n, o),
3763
- onFilterIconClick: (n, o) => this._handleFilterIconClick(n, o),
3764
- getDndManager: () => this._dnd,
3765
- onColDragStart: (n) => {
3766
- this._editMgr.dragColIdx = n;
3767
- },
3768
- onColDrop: (n) => {
3769
- this._editMgr.dragColIdx !== null && this._editMgr.dragColIdx !== n && this._reorderColumn(this._editMgr.dragColIdx, n), this._editMgr.dragColIdx = null;
3770
- },
3771
- getColDragIdx: () => this._editMgr.dragColIdx
3772
- }), this._filterPanel = new Ze(
3773
- this._container,
3774
- (n, o) => this.setFilter(n, o),
3775
- (n) => this.resetFilter(n)
3776
- ), this._container.setAttribute("role", "grid"), this._container.setAttribute("aria-label", this._options.ariaLabel ?? ((s = this._options.cssVars) == null ? void 0 : s["aria-label"]) ?? "OPEN_GRID 데이터 그리드"), this._container.setAttribute("aria-rowcount", "0"), this._container.setAttribute("aria-colcount", String(this._options.columns.filter((n) => !n.hidden).length)), this._liveRegion = document.createElement("div"), this._liveRegion.setAttribute("aria-live", "polite"), this._liveRegion.setAttribute("aria-atomic", "true"), this._liveRegion.className = "og-live-region", this._container.insertAdjacentElement("beforebegin", this._liveRegion), this._container.tabIndex = 0, this._container.addEventListener("keydown", (n) => this._handleKeyDown(n)), this._container.addEventListener("keyup", (n) => this._handleCellKeyEvt("cellKeyUp", n)), this._container.addEventListener("keypress", (n) => this._handleCellKeyEvt("cellKeyPress", n)), this._vs = new Je(this._renderer.bodyWrapper, {
3777
- rowHeight: this._options.rowHeight,
3778
- onRender: (n, o) => this._doRender(n, o)
3779
- }), this._options.draggable && (this._dnd = new Tt(
3780
- this._renderer.bodyWrapper,
3781
- this._options.rowHeight,
3782
- (n, o) => this._handleRowDrop(n, o)
3783
- )), this._options.pagination && (this._pagination = new Lt(
3784
- this._container,
3785
- this._options.pageSize,
3786
- (n) => {
3787
- this.emit("pageChange", n), this._doRender(...this._visRange());
3788
- }
3789
- )), this._findMgr.init(this._container), this._initContextMenu(), (i = this._options.worksheets) != null && i.length && this._initWorksheets(), this._ro = new ResizeObserver(() => this._onResize()), this._ro.observe(this._container), this._onResize();
3790
- }
3791
- _initContextMenu() {
3792
- const e = this._options.contextMenu;
3793
- e !== !1 && (this._cmHandler && this._container.removeEventListener("contextmenu", this._cmHandler), this._cmKbdHandler && this._container.removeEventListener("keydown", this._cmKbdHandler), this._cmHandler = this._cmKbdHandler = null, this._ctxMenu = new $t(this._container, {
3794
- onSortAsc: () => {
3795
- const t = this._colLayout.visibleLeaves[0];
3796
- t && this.orderBy(t.field, "asc");
3797
- },
3798
- onSortDesc: () => {
3799
- const t = this._colLayout.visibleLeaves[0];
3800
- t && this.orderBy(t.field, "desc");
3801
- },
3802
- onFind: () => this._findMgr.open(),
3803
- onExcel: () => this.exportExcel(),
3804
- onCsv: () => this.exportCsv(),
3805
- onPrint: () => this.print()
3806
- }), this._cmHandler = (t) => {
3807
- var l;
3808
- const s = t.target.closest(".og-cell");
3809
- if (!s) return;
3810
- t.preventDefault();
3811
- const i = Number(s.dataset.colIndex ?? -1), n = this._colLayout.visibleLeaves[i];
3812
- n && this._ctxMenu && (this._ctxMenu._actions.onSortAsc = () => this.orderBy(n.field, "asc"), this._ctxMenu._actions.onSortDesc = () => this.orderBy(n.field, "desc"));
3813
- const o = Array.isArray(e) ? e : void 0;
3814
- (l = this._ctxMenu) == null || l.open(t, o);
3815
- }, this._container.addEventListener("contextmenu", this._cmHandler), this._cmKbdHandler = (t) => {
3816
- var s;
3817
- if (t.shiftKey && t.key === "F10") {
3818
- t.preventDefault();
3819
- const i = this._container.getBoundingClientRect(), n = { clientX: i.left + 80, clientY: i.top + 40 };
3820
- (s = this._ctxMenu) == null || s.open(n);
3821
- }
3822
- }, this._container.addEventListener("keydown", this._cmKbdHandler));
3823
- }
3824
- // openContextMenu / closeContextMenu 공개 API
3825
- openContextMenu(e, t) {
3826
- var s;
3827
- (s = this._ctxMenu) == null || s.open(e, t);
3828
- }
3829
- closeContextMenu() {
3830
- var e;
3831
- (e = this._ctxMenu) == null || e.close();
3832
- }
3833
- setFilterSelect(e) {
3834
- var t;
3835
- (t = this._filterSelect) == null || t.destroy(), this._filterSelect = null, e && (this._container.id || (this._container.id = `og-${Math.random().toString(36).slice(2, 7)}`), this._filterSelect = new St(
3836
- this._container,
3837
- e,
3838
- (s, i) => this.setFilter(s, i),
3839
- (s) => this.resetFilter(s),
3840
- this._container.id
3841
- ));
3842
- }
3843
- // 옵션을 런타임에 바꿀 때 호출 (contextMenu 재초기화, groupBy 재구성 등)
3844
- setOptions(e) {
3845
- var t;
3846
- if (Object.assign(this._options, e), "contextMenu" in e && ((t = this._ctxMenu) == null || t.destroy(), this._ctxMenu = null, this._initContextMenu()), "groupBy" in e || "summary" in e) {
3847
- const s = e.groupBy ?? [];
3848
- s.length > 0 ? this._grpMgr.groupBy(s) : this.clearGroup();
3849
- return;
3850
- }
3851
- this._renderHeader(), this._doRender(...this._visRange());
3852
- }
3853
- /**
3854
- * 컬럼 마스킹 ON/OFF 전환.
3855
- * enabled=true → 마스킹 적용 (기본 상태)
3856
- * enabled=false → 컬럼 전체 마스킹 해제 (원문 표시)
3857
- */
3858
- setMaskEnabled(e, t) {
3859
- var i;
3860
- const s = this._colLayout.getColumnByField(e);
3861
- s && (t ? (s._maskRevealed = !1, (i = s._maskRevealedRows) == null || i.clear()) : s._maskRevealed = !0, this._doRender(...this._visRange()));
3862
- }
3863
- /** 현재 컬럼 마스킹 활성 여부 반환. true=마스킹 중, false=해제됨 */
3864
- getMaskEnabled(e) {
3865
- const t = this._colLayout.getColumnByField(e);
3866
- return t ? t._maskRevealed !== !0 : !1;
3867
- }
3868
- _initWorksheets() {
3869
- const e = this._options.worksheets;
3870
- this._wsManager = new ze(
3871
- this._container,
3872
- (t, s) => {
3873
- this._data.setData(s.data), this._colLayout = new le(
3874
- s.columns.length ? s.columns : this._options.columns,
3875
- this._options.frozenColumns
3876
- ), this._doRender(...this._visRange()), this._renderHeader();
3877
- }
3878
- );
3879
- for (const t of e)
3880
- this._wsManager.add(t.name, t.columns ?? this._options.columns, t.data ?? []);
3881
- }
3882
- addWorksheet(e, t, s) {
3883
- this._wsManager || (this._wsManager = new ze(
3884
- this._container,
3885
- (i, n) => {
3886
- this._data.setData(n.data), this._colLayout = new le(
3887
- n.columns.length ? n.columns : this._options.columns,
3888
- this._options.frozenColumns
3889
- ), this._doRender(...this._visRange()), this._renderHeader();
3890
- }
3891
- )), this._wsManager.add(e, t ?? this._options.columns, s ?? []);
3892
- }
3893
- removeWorksheet(e) {
3894
- var t;
3895
- (t = this._wsManager) == null || t.remove(e);
3896
- }
3897
- switchWorksheet(e) {
3898
- var t;
3899
- (t = this._wsManager) == null || t.switch(e);
3900
- }
3901
- renameWorksheet(e, t) {
3902
- var s;
3903
- (s = this._wsManager) == null || s.rename(e, t);
3904
- }
3905
- getWorksheet(e) {
3906
- var t;
3907
- return (t = this._wsManager) == null ? void 0 : t.get(e);
3908
- }
3909
- getWorksheetNames() {
3910
- var e;
3911
- return ((e = this._wsManager) == null ? void 0 : e.getNames()) ?? [];
3912
- }
3913
- exportSheetsExcel(e) {
3914
- this._exportMgr.exportSheetsExcel(e);
3915
- }
3916
- _paginationHeight() {
3917
- return this._options.pagination ? 38 : 0;
3918
- }
3919
- _onResize() {
3920
- const { width: e, height: t } = this._container.getBoundingClientRect();
3921
- if (!e) return;
3922
- const s = t - this._options.headerHeight - this._paginationHeight();
3923
- this._renderer.updateSize(t - this._paginationHeight(), this._options.headerHeight), this._vs.setViewportHeight(s), this._recalcWidths(e), this._renderHeader(), this._doRender(...this._visRange());
3924
- }
3925
- _recalcWidths(e) {
3926
- this._colWidths = this._colLayout.computeWidths(
3927
- e - (this._options.stateColumn ? 24 : 0) - (this._options.draggable ? 18 : 0) - (this._options.rowNumber ? 44 : 0) - (this._options.checkColumn ? 36 : 0),
3928
- this._options.defaultColumnWidth
3929
- );
3930
- }
3931
- // 헤더(컬럼 제목 행)를 다시 그린다
3932
- _renderHeader() {
3933
- var e;
3934
- (e = this._renderer) == null || e.renderHeader(
3935
- this._colLayout.buildHeaderCells(),
3936
- this._colLayout.visibleLeaves,
3937
- this._colWidths,
3938
- this._sfMgr.sortList,
3939
- { ...this._options, _activeFilters: this._sfMgr.filters, _frozenCount: this._colLayout.frozenCount }
3940
- );
3941
- }
3942
- _doRender(e, t) {
3943
- var i;
3944
- if (!this._renderer || !this._vs) return;
3945
- const s = this._vs.getVisibleRange();
3946
- this._renderer.renderBody(
3947
- e,
3948
- t,
3949
- this._data,
3950
- this._colLayout.visibleLeaves,
3951
- this._colWidths,
3952
- this._options,
3953
- s.offsetY,
3954
- this._vs.getTotalHeight(),
3955
- this._rowMgr.selectedRows,
3956
- this._rowMgr.checkedRows,
3957
- this._grpMgr.isGroupMode ? this._grpMgr.groupFlatRows : this._grpMgr.isTreeMode ? this._grpMgr.treeFlatRows : null,
3958
- (n) => this._grpMgr.handleGroupToggle(n),
3959
- this._grpMgr.isTreeMode ? (n) => this._grpMgr.handleTreeToggle(n) : void 0,
3960
- { _totalRows: this._data.rowCount, _frozenCount: this._colLayout.frozenCount, _focusCell: this._editMgr.focusCell },
3961
- this._mergeEngine
3962
- ), (i = this._options.footer) != null && i.length && this._renderFooterEl();
3963
- }
3964
- _handleGroupToggle(e) {
3965
- this._grpMgr.handleGroupToggle(e);
3966
- }
3967
- // 현재 화면에 보이는 행 범위를 반환한다
3968
- _visRange() {
3969
- var t;
3970
- if (this._options.pagination && this._pagination) {
3971
- const { start: s, end: i } = this._pagination.getRange();
3972
- return [s, i];
3973
- }
3974
- const e = (t = this._vs) == null ? void 0 : t.getVisibleRange();
3975
- return [(e == null ? void 0 : e.startIndex) ?? 0, Math.min(((e == null ? void 0 : e.endIndex) ?? 30) + this._visCount() + 5, this._data.rowCount - 1)];
3976
- }
3977
- _visCount() {
3978
- const e = this._container.getBoundingClientRect().height;
3979
- return Math.ceil((e - this._options.headerHeight - this._paginationHeight()) / this._options.rowHeight) + 5;
3980
- }
3981
- _handleSortClick(e, t) {
3982
- this._sfMgr.handleSortClick(e, t);
3983
- }
3984
- _isToggleCol(e) {
3985
- return ee(e);
3986
- }
3987
- _handleCellClick(e, t, s) {
3988
- this._cellEvt.handleCellClick(e, t, s);
3989
- }
3990
- _handleCellDblClick(e, t, s) {
3991
- this._cellEvt.handleCellDblClick(e, t, s);
3992
- }
3993
- _handleCellMouseOver(e, t, s) {
3994
- this._cellEvt.handleCellMouseOver(e, t, s);
3995
- }
3996
- _handleCellMouseOut(e, t, s) {
3997
- this._cellEvt.handleCellMouseOut(e, t, s);
3998
- }
3999
- _handleCellMouseDown(e, t, s) {
4000
- this._cellEvt.handleCellMouseDown(e, t, s);
4001
- }
4002
- _handleCellMouseUp(e, t, s) {
4003
- this._cellEvt.handleCellMouseUp(e, t, s);
4004
- }
4005
- _handleCellMouseMove(e, t, s) {
4006
- this._cellEvt.handleCellMouseMove(e, t, s);
4007
- }
4008
- _handleCellKeyEvt(e, t) {
4009
- this._cellEvt.handleCellKeyEvt(e, t);
4010
- }
4011
- _handleRowCheck(e, t) {
4012
- this._rowMgr.check(e, t), this._doRender(...this._visRange()), this.emit("rowCheck", { rowIndex: e, checked: t, row: this._data.getRowByIndex(e) });
4013
- }
4014
- _handleFilterIconClick(e, t) {
4015
- var i, n;
4016
- if ((i = this._filterPanel) != null && i.isOpen) {
4017
- this._filterPanel.close();
4018
- return;
4019
- }
4020
- const s = this._sfMgr.filters[e] ?? [];
4021
- (n = this._filterPanel) == null || n.open(e, t, s);
4022
- }
4023
- _handleAllCheck(e) {
4024
- this._rowMgr.checkAll(e, this._data.rowCount), this._doRender(...this._visRange()), this.emit("allCheck", { checked: e });
4025
- }
4026
- _handleRowDrop(e, t) {
4027
- var s, i;
4028
- this._data.moveRow(e, t), this._doRender(...this._visRange()), this.emit("rowDrop", { fromIndex: e, toIndex: t }), (i = (s = this._options).onRowDrop) == null || i.call(s, { fromIndex: e, toIndex: t });
4029
- }
4030
- /** 행을 드롭으로 이동할 때 실행된다 */
4031
- /** ???꾩튂 ?대룞 */
4032
- reorderRow(e, t) {
4033
- this._data.moveRow(e, t), this._doRender(...this._visRange());
4034
- }
4035
- _handleColResize(e, t) {
4036
- this._colWidths[e] !== void 0 && (this._colWidths[e] = t), this._doRender(...this._visRange());
4037
- }
4038
- _handleKeyDown(e) {
4039
- this._kbdMgr.handleKeyDown(e);
4040
- }
4041
- _setFocusCell(e, t) {
4042
- this._rowMgr.selectSingle(e), this._editMgr.setFocusCell(e, t);
4043
- }
4044
- // 스크린리더에게 텍스트를 읽어준다 (aria-live)
4045
- _announce(e) {
4046
- this._liveRegion && (this._liveRegion.textContent = "", setTimeout(() => {
4047
- this._liveRegion && (this._liveRegion.textContent = e);
4048
- }, 50));
4049
- }
4050
- _bindOptionEvents() {
4051
- this._options.onCellClick && this.on("cellClick", this._options.onCellClick), this._options.onCellDblClick && this.on("cellDblClick", this._options.onCellDblClick), this._options.onRowClick && this.on("rowClick", this._options.onRowClick), this._options.onEditStart && this.on("editStart", this._options.onEditStart), this._options.onEditEnd && this.on("editEnd", this._options.onEditEnd), this._options.onSortChange && this.on("sortChange", this._options.onSortChange), this._options.onFilterChange && this.on("filterChange", this._options.onFilterChange), this._options.onScroll && this.on("scroll", this._options.onScroll), this._options.onDataChange && this.on("dataChange", this._options.onDataChange), this._options.onSelectionChange && this.on("selectionChange", this._options.onSelectionChange), this._options.onRowDblClick && this.on("rowDblClick", this._options.onRowDblClick), this._options.onRowMouseOver && this.on("rowMouseOver", this._options.onRowMouseOver), this._options.onRowMouseOut && this.on("rowMouseOut", this._options.onRowMouseOut), this._options.onRowMouseDown && this.on("rowMouseDown", this._options.onRowMouseDown), this._options.onRowMouseUp && this.on("rowMouseUp", this._options.onRowMouseUp), this._options.onRowMouseMove && this.on("rowMouseMove", this._options.onRowMouseMove), this._options.onCellMouseOver && this.on("cellMouseOver", this._options.onCellMouseOver), this._options.onCellMouseOut && this.on("cellMouseOut", this._options.onCellMouseOut), this._options.onCellMouseDown && this.on("cellMouseDown", this._options.onCellMouseDown), this._options.onCellMouseUp && this.on("cellMouseUp", this._options.onCellMouseUp), this._options.onCellMouseMove && this.on("cellMouseMove", this._options.onCellMouseMove), this._options.onCellKeyDown && this.on("cellKeyDown", this._options.onCellKeyDown), this._options.onCellKeyUp && this.on("cellKeyUp", this._options.onCellKeyUp), this._options.onCellKeyPress && this.on("cellKeyPress", this._options.onCellKeyPress);
4052
- }
4053
- setData(e) {
4054
- var s;
4055
- const t = this._trigMgr.mkCtx("setData", [e]);
4056
- this._trigMgr.exec("before:setData", t) && (this._rowMgr.reset(), this._data.setData(e), this._applyFilters(), this._grpMgr.isTreeMode ? this._grpMgr.rebuildTree() : this._grpMgr.isGroupMode ? this._grpMgr.rebuildGroups() : (s = this._vs) == null || s.setTotalRows(this._data.rowCount), this._container.setAttribute("aria-rowcount", String(this._data.rowCount)), this._container.setAttribute("aria-colcount", String(this._colLayout.visibleLeaves.length)), this._announce(`${this._data.rowCount}행 데이터 로드됨`), this.emit("dataChange", this._data.getData()), t.result = e.length, this._trigMgr.exec("after:setData", t));
4057
- }
4058
- getData() {
4059
- return this._data.getData();
4060
- }
4061
- getSourceRows() {
4062
- return this._data.getOriginalData();
4063
- }
4064
- pushData(e) {
4065
- var i, n;
4066
- const t = [...this._data.getAllData(), ...e];
4067
- this._data.setData(t);
4068
- const s = this._data.rowCount;
4069
- (i = this._vs) == null || i.setTotalRows(s), (n = this._pagination) == null || n.setTotalRows(s);
4070
- }
4071
- prefixData(e) {
4072
- var i, n;
4073
- const t = [...e, ...this._data.getAllData()];
4074
- this._data.setData(t);
4075
- const s = this._data.rowCount;
4076
- (i = this._vs) == null || i.setTotalRows(s), (n = this._pagination) == null || n.setTotalRows(s);
4077
- }
4078
- clearData() {
4079
- var e, t;
4080
- this._rowMgr.reset(), this._data.clearData(), (e = this._vs) == null || e.setTotalRows(0), (t = this._pagination) == null || t.setTotalRows(0), this._doRender(0, -1), this.emit("dataChange", []);
4081
- }
4082
- insertRow(e, t = "last") {
4083
- var o, l, r, a;
4084
- const s = this._trigMgr.mkCtx("insertRow", [e, t]);
4085
- if (!this._trigMgr.exec("before:insertRow", s)) return;
4086
- const i = t === "before" ? 0 : t === "after" ? this._data.rowCount : t;
4087
- this._data.addRow(e, i);
4088
- const n = this._data.rowCount;
4089
- (o = this._vs) == null || o.setTotalRows(n), (l = this._pagination) == null || l.setTotalRows(n), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (a = (r = this._options).onDataChange) == null || a.call(r, this._data.getData()), s.result = { rowCount: n, item: e }, this._trigMgr.exec("after:insertRow", s);
4090
- }
4091
- pushRow(e) {
4092
- var i, n, o, l;
4093
- (Array.isArray(e) ? e : [e]).forEach((r) => this._data.addRow(r, "last"));
4094
- const s = this._data.rowCount;
4095
- (i = this._vs) == null || i.setTotalRows(s), (n = this._pagination) == null || n.setTotalRows(s), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (l = (o = this._options).onDataChange) == null || l.call(o, this._data.getData());
4096
- }
4097
- /** @deprecated 하위호환 alias → pushRow */
4098
- appendRows(e) {
4099
- this.pushRow(e);
4100
- }
4101
- unshiftRow(e) {
4102
- var i, n, o, l;
4103
- (Array.isArray(e) ? e : [e]).forEach((r) => this._data.addRow(r, "first"));
4104
- const s = this._data.rowCount;
4105
- (i = this._vs) == null || i.setTotalRows(s), (n = this._pagination) == null || n.setTotalRows(s), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (l = (o = this._options).onDataChange) == null || l.call(o, this._data.getData());
4106
- }
4107
- /** @deprecated 하위호환 alias → unshiftRow */
4108
- prependRows(e) {
4109
- this.unshiftRow(e);
4110
- }
4111
- deleteRow(e) {
4112
- var o, l, r, a;
4113
- const t = this._trigMgr.mkCtx("deleteRow", [e]), s = Array.isArray(e) ? [...e] : [e];
4114
- if (t.extra = { rows: s.map((c) => this._data.getRowByIndex(c)) }, !this._trigMgr.exec("before:deleteRow", t)) return;
4115
- const i = s.sort((c, h) => h - c);
4116
- i.forEach((c) => this._data.removeRow(c));
4117
- const n = this._data.rowCount;
4118
- (o = this._vs) == null || o.setTotalRows(n), (l = this._pagination) == null || l.setTotalRows(n), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (a = (r = this._options).onDataChange) == null || a.call(r, this._data.getData()), t.result = { deleted: i.length, rowCount: n }, this._trigMgr.exec("after:deleteRow", t);
4119
- }
4120
- deleteById(e) {
4121
- }
4122
- readCell(e, t) {
4123
- return this._data.getCellValue(e, t);
4124
- }
4125
- getDisplayValue(e, t) {
4126
- const s = this.readCell(e, t);
4127
- return s == null ? "" : String(s);
4128
- }
4129
- writeCell(e, t, s) {
4130
- var c, h, u, g;
4131
- const i = this.readCell(e, t), n = this._trigMgr.mkCtx("writeCell", [e, t, s]);
4132
- if (n.extra = { oldValue: i, rowIndex: e, field: t }, !this._trigMgr.exec("before:writeCell", n)) return;
4133
- this._data.updateCell(e, t, s);
4134
- const o = this._data.getRowByIndex(e), l = this._colLayout.getColumnByField(t), r = this._colLayout.getColumnIndex(t), a = { type: "editEnd", rowIndex: e, columnIndex: r, field: t, oldValue: i, newValue: s, row: o, column: l };
4135
- this.emit("editEnd", a), (h = (c = this._options).onEditEnd) == null || h.call(c, a), this.emit("dataChange", this._data.getData()), (g = (u = this._options).onDataChange) == null || g.call(u, this._data.getData()), this._doRender(...this._visRange()), n.result = { rowIndex: e, field: t, oldValue: i, newValue: s }, this._trigMgr.exec("after:writeCell", n);
4136
- }
4137
- getRowAt(e) {
4138
- return this._data.getRowByIndex(e);
4139
- }
4140
- getChanges() {
4141
- return this._data.getChanges();
4142
- }
4143
- getEditedRows() {
4144
- return this._data.getEditedRows();
4145
- }
4146
- getChangedRows() {
4147
- return this._data.getChangedRows();
4148
- }
4149
- // ?섏쐞 ?명솚
4150
- getChangedColumns() {
4151
- return this._data.getChangedColumns();
4152
- }
4153
- getAddedRows() {
4154
- return this._data.getAddedRows();
4155
- }
4156
- getRemovedRows() {
4157
- return this._data.getRemovedRows();
4158
- }
4159
- getOriginalRow(e) {
4160
- return this._data.getOriginalRow(e);
4161
- }
4162
- getRowsWithState(e) {
4163
- return this._data.getRowsWithState(e);
4164
- }
4165
- undo() {
4166
- }
4167
- redo() {
4168
- }
4169
- clearHistory() {
4170
- }
4171
- getColumnDefs() {
4172
- return this._colLayout.visibleLeaves;
4173
- }
4174
- getAllColumnDefs() {
4175
- return this._colLayout.leaves;
4176
- }
4177
- getColumnCount() {
4178
- return this._colLayout.visibleLeaves.length;
4179
- }
4180
- applyColumns(e) {
4181
- const t = this._trigMgr.mkCtx("applyColumns", [e]);
4182
- this._trigMgr.exec("before:applyColumns", t) && (this._colLayout.setColumns(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange()), t.result = { columnCount: e.length }, this._trigMgr.exec("after:applyColumns", t));
4183
- }
4184
- insertColumn(e, t) {
4185
- this._colLayout.addColumn(e, t), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4186
- }
4187
- deleteColumn(e) {
4188
- this._colLayout.removeColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4189
- }
4190
- _reorderColumn(e, t) {
4191
- var o, l;
4192
- const s = this._colLayout.visibleLeaves.map((r) => r);
4193
- if (e < 0 || t < 0 || e >= s.length || t >= s.length) return;
4194
- const i = [...this._options.columns], [n] = i.splice(e, 1);
4195
- i.splice(t, 0, n), this._options.columns = i, this.applyColumns(i), (l = (o = this._options).onColumnReorder) == null || l.call(o, { fromIndex: e, toIndex: t, field: n.field ?? "" });
4196
- }
4197
- hideColumn(e) {
4198
- this._colLayout.hideColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4199
- }
4200
- showColumn(e) {
4201
- this._colLayout.showColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4202
- }
4203
- getColumnIndex(e) {
4204
- return this._colLayout.getColumnIndex(e);
4205
- }
4206
- getFieldAt(e) {
4207
- var t;
4208
- return ((t = this._colLayout.getColumnByIndex(e)) == null ? void 0 : t.field) ?? "";
4209
- }
4210
- getColValues(e, t = !1) {
4211
- return this._data.getData().map((s) => s[e]);
4212
- }
4213
- getUniqueValues(e, t = !1) {
4214
- return [...new Set(this.getColValues(e, t))];
4215
- }
4216
- setColWidths(e) {
4217
- }
4218
- calcColWidths(e = !1) {
4219
- return [];
4220
- }
4221
- getSelections() {
4222
- return this._rowMgr.getSelections();
4223
- }
4224
- getActiveRow() {
4225
- return this._rowMgr.getActiveRow();
4226
- }
4227
- activate(e) {
4228
- this._rowMgr.activate(e), this._doRender(...this._visRange());
4229
- }
4230
- deselect() {
4231
- this._rowMgr.deselect(), this._doRender(...this._visRange());
4232
- }
4233
- getChecked() {
4234
- return this._rowMgr.getChecked();
4235
- }
4236
- getAllChecked() {
4237
- return this._rowMgr.getAllChecked();
4238
- }
4239
- checkById(e) {
4240
- }
4241
- addCheckById(e) {
4242
- }
4243
- checkByValue(e, t) {
4244
- this._rowMgr.checkByValue(e, t), this._doRender(...this._visRange());
4245
- }
4246
- uncheckById(e) {
4247
- }
4248
- uncheckAll() {
4249
- this._rowMgr.uncheckAll(), this._doRender(...this._visRange());
4250
- }
4251
- orderBy(e, t = "asc") {
4252
- const s = this._trigMgr.mkCtx("orderBy", [e, t]);
4253
- this._trigMgr.exec("before:orderBy", s) && (this._sfMgr.sort(e, t), s.result = { sortList: this._sfMgr.sortList }, this._trigMgr.exec("after:orderBy", s));
4254
- }
4255
- resetOrder() {
4256
- this._sfMgr.resetSort();
4257
- }
4258
- setFilter(e, t) {
4259
- const s = this._trigMgr.mkCtx("setFilter", [e, t]);
4260
- this._trigMgr.exec("before:setFilter", s) && (this._sfMgr.setFilter(e, t), s.result = { field: e, filteredCount: this._data.rowCount }, this._trigMgr.exec("after:setFilter", s));
4261
- }
4262
- resetFilter(e) {
4263
- this._sfMgr.resetFilter(e);
4264
- }
4265
- getFilterState() {
4266
- return this._sfMgr.getFilterState();
4267
- }
4268
- restoreFilter(e) {
4269
- this._sfMgr.restoreFilter(e);
4270
- }
4271
- _applyFilters() {
4272
- this._sfMgr.applyFilters();
4273
- }
4274
- freeze(e) {
4275
- this._colLayout.setFrozen(e), this._renderHeader(), this._doRender(...this._visRange());
4276
- }
4277
- /** ?섎룞 蹂묓빀: [{row, col, rowSpan?, colSpan?}] */
4278
- mergeCells(e) {
4279
- this._mergeEngine.applyMergeCells(e), this._doRender(...this._visRange());
4280
- }
4281
- /** 자동 병합: 지정 필드 컬럼에서 연속 같은 값을 rowSpan으로 묶는다 */
4282
- /** ?먮룞 蹂묓빀: 吏€??field 而щ읆?먯꽌 ?곗냽 媛숈? 媛믪쓣 rowSpan */
4283
- autoMerge(e) {
4284
- const t = this._colLayout.visibleLeaves, s = [], i = [];
4285
- for (const n of e) {
4286
- const o = t.findIndex((l) => l.field === n);
4287
- o >= 0 && (s.push(o), i.push(n));
4288
- }
4289
- this._mergeEngine.applyAutoMerge(this._data.getData(), s, i), this._doRender(...this._visRange());
4290
- }
4291
- /** 蹂묓빀 ?댁젣 */
4292
- clearMerge() {
4293
- this._mergeEngine.clear(), this._doRender(...this._visRange());
4294
- }
4295
- freezeRows(e) {
4296
- }
4297
- groupBy(e) {
4298
- const t = this._trigMgr.mkCtx("groupBy", [e]);
4299
- this._trigMgr.exec("before:groupBy", t) && (this._grpMgr.groupBy(e), t.result = { fields: e }, this._trigMgr.exec("after:groupBy", t));
4300
- }
4301
- clearGroup() {
4302
- this._grpMgr.clearGroup();
4303
- }
4304
- expandAll() {
4305
- this._grpMgr.expandAll();
4306
- }
4307
- collapseAll() {
4308
- this._grpMgr.collapseAll();
4309
- }
4310
- enableTree() {
4311
- this._grpMgr.enableTree();
4312
- }
4313
- disableTree() {
4314
- this._grpMgr.disableTree();
4315
- }
4316
- expandNodes(e, t = !0) {
4317
- this._grpMgr.expandNodes(e, t);
4318
- }
4319
- expandAllNodes() {
4320
- this._grpMgr.expandAllNodes();
4321
- }
4322
- collapseAllNodes() {
4323
- this._grpMgr.collapseAllNodes();
4324
- }
4325
- addTreeRow(e, t, s) {
4326
- }
4327
- exportExcel(e) {
4328
- this._exportMgr.exportExcel(e);
4329
- }
4330
- exportCsv(e) {
4331
- this._exportMgr.exportCsv(e);
4332
- }
4333
- exportJson(e) {
4334
- this._exportMgr.exportJson(e);
4335
- }
4336
- print(e) {
4337
- this._exportMgr.print(e);
4338
- }
4339
- toArray(e = !0) {
4340
- const t = this._data.getData();
4341
- if (e) return t;
4342
- const s = this._colLayout.visibleLeaves;
4343
- return t.map((i) => s.map((n) => i[n.field]));
4344
- }
4345
- jumpToRow(e) {
4346
- var t;
4347
- this._rowMgr.selectSingle(e), (t = this._vs) == null || t.scrollToRow(e), this._doRender(...this._visRange());
4348
- }
4349
- jumpToCol(e) {
4350
- }
4351
- getScrollPos() {
4352
- var e, t;
4353
- return { x: ((e = this._renderer) == null ? void 0 : e.bodyWrapper.scrollLeft) ?? 0, y: ((t = this._renderer) == null ? void 0 : t.bodyWrapper.scrollTop) ?? 0 };
4354
- }
4355
- setFooter(e) {
4356
- this._options.footer = e, this._renderFooterEl();
4357
- }
4358
- getFooterData() {
4359
- return this._footerMgr.computeValues();
4360
- }
4361
- getFooterValue(e) {
4362
- var t;
4363
- return ((t = this._footerMgr.computeValues().find((s) => s._field === e)) == null ? void 0 : t._value) ?? null;
4364
- }
4365
- _renderFooterEl() {
4366
- this._footerMgr.render();
4367
- }
4368
- resize(e, t) {
4369
- e && (this._container.style.width = `${e}px`), t && (this._container.style.height = `${t}px`), this._onResize();
4370
- }
4371
- setTheme(e) {
4372
- this._container.setAttribute("data-og-theme", e);
4373
- }
4374
- setThemeVar(e, t) {
4375
- this._container.style.setProperty(e, t);
4376
- }
4377
- addTrigger(e, t) {
4378
- return this._trigMgr.add(e, t), this;
4379
- }
4380
- removeTrigger(e, t) {
4381
- return this._trigMgr.remove(e, t), this;
4382
- }
4383
- clearTriggers(e) {
4384
- return this._trigMgr.clear(e), this;
4385
- }
4386
- _mkCtx(e, t) {
4387
- return this._trigMgr.mkCtx(e, t);
4388
- }
4389
- _trig(e, t) {
4390
- return this._trigMgr.exec(e, t);
4391
- }
4392
- destroy() {
4393
- var e, t, s, i, n, o, l, r;
4394
- this._destroyed || (this._destroyed = !0, this._trigMgr.clear(), (e = this._ro) == null || e.disconnect(), (t = this._vs) == null || t.destroy(), (s = this._filterPanel) == null || s.destroy(), (i = this._dnd) == null || i.destroy(), this._cmHandler && this._container.removeEventListener("contextmenu", this._cmHandler), this._cmKbdHandler && this._container.removeEventListener("keydown", this._cmKbdHandler), this._cmHandler = this._cmKbdHandler = null, (n = this._ctxMenu) == null || n.destroy(), (o = this._wsManager) == null || o.destroy(), (l = this._renderer) == null || l.destroy(), (r = this._liveRegion) == null || r.remove(), this._liveRegion = null, this._container.innerHTML = "", this._container.classList.remove("og-container"), this.removeAllListeners());
4395
- }
4396
- }
4397
- export {
4398
- Xt as O,
4399
- He as b
4400
- };
4401
- //# sourceMappingURL=OpenGrid-Dult64jp.js.map