open-grid 0.2.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/dist/OpenGrid-CAodJLLm.cjs +90 -0
  4. package/dist/OpenGrid-CAodJLLm.cjs.map +1 -0
  5. package/dist/OpenGrid-CfZy3e7Q.js +4376 -0
  6. package/dist/OpenGrid-CfZy3e7Q.js.map +1 -0
  7. package/dist/open-grid-base.css +1595 -0
  8. package/dist/open-grid-react.cjs +2 -0
  9. package/dist/open-grid-react.cjs.map +1 -0
  10. package/dist/open-grid-react.js +91 -0
  11. package/dist/open-grid-react.js.map +1 -0
  12. package/dist/open-grid-themes.css +630 -0
  13. package/dist/open-grid-vue.cjs +2 -0
  14. package/dist/open-grid-vue.cjs.map +1 -0
  15. package/dist/open-grid-vue.js +84 -0
  16. package/dist/open-grid-vue.js.map +1 -0
  17. package/dist/open-grid.cjs +7 -0
  18. package/dist/open-grid.cjs.map +1 -0
  19. package/dist/open-grid.js +311 -0
  20. package/dist/open-grid.js.map +1 -0
  21. package/dist/types/bench/perf.d.ts +16 -0
  22. package/dist/types/core/CellEditManager.d.ts +46 -0
  23. package/dist/types/core/CellEventHandler.d.ts +28 -0
  24. package/dist/types/core/CellTypeRegistry.d.ts +5 -0
  25. package/dist/types/core/ColumnLayout.d.ts +41 -0
  26. package/dist/types/core/ContextMenu.d.ts +33 -0
  27. package/dist/types/core/DataLayer.d.ts +65 -0
  28. package/dist/types/core/EventEmitter.d.ts +11 -0
  29. package/dist/types/core/ExportManager.d.ts +28 -0
  30. package/dist/types/core/FilterPanel.d.ts +20 -0
  31. package/dist/types/core/FilterSelect.d.ts +96 -0
  32. package/dist/types/core/FindBarManager.d.ts +26 -0
  33. package/dist/types/core/FooterManager.d.ts +16 -0
  34. package/dist/types/core/FormulaEngine.d.ts +10 -0
  35. package/dist/types/core/GridRenderer.d.ts +42 -0
  36. package/dist/types/core/GroupEngine.d.ts +47 -0
  37. package/dist/types/core/GroupTreeManager.d.ts +43 -0
  38. package/dist/types/core/KeyboardManager.d.ts +26 -0
  39. package/dist/types/core/MaskingEngine.d.ts +25 -0
  40. package/dist/types/core/MathUtils.d.ts +26 -0
  41. package/dist/types/core/MergeEngine.d.ts +35 -0
  42. package/dist/types/core/OGDecimal.d.ts +49 -0
  43. package/dist/types/core/OpenGrid.d.ts +213 -0
  44. package/dist/types/core/OrgChart.d.ts +35 -0
  45. package/dist/types/core/Pagination.d.ts +34 -0
  46. package/dist/types/core/PivotEngine.d.ts +20 -0
  47. package/dist/types/core/RowDragDrop.d.ts +18 -0
  48. package/dist/types/core/RowManager.d.ts +30 -0
  49. package/dist/types/core/SortFilterManager.d.ts +36 -0
  50. package/dist/types/core/TreeEngine.d.ts +34 -0
  51. package/dist/types/core/TriggerManager.d.ts +10 -0
  52. package/dist/types/core/VirtualScroll.d.ts +31 -0
  53. package/dist/types/core/WorksheetManager.d.ts +24 -0
  54. package/dist/types/core/XmlConverter.d.ts +88 -0
  55. package/dist/types/core/editors/CellEditor.d.ts +55 -0
  56. package/dist/types/core/editors/DateEditor.d.ts +15 -0
  57. package/dist/types/core/editors/SelectEditor.d.ts +21 -0
  58. package/dist/types/core/renderers/CellRenderer.d.ts +138 -0
  59. package/dist/types/core/types.d.ts +497 -0
  60. package/dist/types/index.d.ts +9 -0
  61. package/dist/types/react/OpenGrid.d.ts +34 -0
  62. package/dist/types/react/index.d.ts +2 -0
  63. package/dist/types/vue/OpenGrid.vue.d.ts +80 -0
  64. package/dist/types/vue/index.d.ts +2 -0
  65. package/dist/types/vue/types.d.ts +28 -0
  66. package/dist/xlsx.min-Bx-LxWOf.cjs +138 -0
  67. package/dist/xlsx.min-Bx-LxWOf.cjs.map +1 -0
  68. package/dist/xlsx.min-Wavxcamn.js +11907 -0
  69. package/dist/xlsx.min-Wavxcamn.js.map +1 -0
  70. package/package.json +102 -0
@@ -0,0 +1,4376 @@
1
+ class qe {
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 n = s.filter((i) => i.handler !== t);
19
+ n.length === 0 ? this.listeners.delete(e) : this.listeners.set(e, n);
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 n = [];
27
+ for (const i of s)
28
+ i.handler(...t), i.once || n.push(i);
29
+ return n.length !== s.length && (n.length === 0 ? this.listeners.delete(e) : this.listeners.set(e, n)), !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 Ye = 0;
40
+ function Me() {
41
+ return `og-r-${++Ye}`;
42
+ }
43
+ class Xe {
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(), n = { ...t, [this._idField]: s };
51
+ return this._meta.set(s, { state: "none", rowId: s }), n;
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(), n = { ...e, [this._idField]: s };
75
+ if (this._meta.set(s, { state: "added", rowId: s }), t === "last") {
76
+ const i = this._data.push(n) - 1;
77
+ this._idMap.set(s, i), this._displayIndexes.push(i);
78
+ } else if (t === "first")
79
+ this._data.unshift(n), this._rebuildIdMap(), this._displayIndexes.unshift(0);
80
+ else {
81
+ const i = Math.min(t, this._displayIndexes.length), o = i < this._displayIndexes.length ? this._displayIndexes[i] : this._data.length;
82
+ this._data.splice(o, 0, n), 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], n = s[this._idField], i = this._meta.get(n);
89
+ return (i == null ? void 0 : i.state) === "added" ? (this._data.splice(t, 1), this._meta.delete(n)) : this._meta.set(n, { ...i, 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], n = this._displayIndexes[t];
96
+ if (s === void 0 || n === void 0) return;
97
+ const [i] = this._data.splice(s, 1), o = s < n ? n - 1 : n;
98
+ this._data.splice(o, 0, i), 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 n = this._displayIndexes[e];
105
+ if (n === void 0) return !1;
106
+ const o = this._data[n][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[n] }
111
+ }), this._data[n][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 n of this._data) {
158
+ const i = n[this._idField], o = this._meta.get(i), l = (o == null ? void 0 : o.state) ?? "none";
159
+ if (l === "added")
160
+ e.push({ ...n });
161
+ else if (l === "removed")
162
+ s.push({ ...n });
163
+ else if (l === "edited") {
164
+ const r = o.original ?? {}, a = Object.keys(n).filter(
165
+ (c) => c !== this._idField && n[c] !== r[c]
166
+ );
167
+ t.push({ ...n, _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 n;
182
+ const t = ((n = this._meta.get(e[this._idField])) == null ? void 0 : n.original) ?? {}, s = [];
183
+ for (const i of Object.keys(e))
184
+ i !== this._idField && e[i] !== t[i] && s.push({ field: i, oldValue: t[i], newValue: e[i] });
185
+ return { row: { ...e }, fields: s.map((i) => i.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], n = this._meta.get(s[this._idField]);
193
+ if (!(!n || n.state === "added"))
194
+ return n.state === "edited" && n.original ? { ...n.original } : { ...this._original[t] };
195
+ }
196
+ getRowsWithState(e) {
197
+ return this._data.map((t) => {
198
+ var n;
199
+ const s = ((n = this._meta.get(t[this._idField])) == null ? void 0 : n.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 = (n) => {
211
+ var i, o;
212
+ return ((o = this._meta.get((i = this._data[n]) == null ? void 0 : i[this._idField])) == null ? void 0 : o.state) !== "removed";
213
+ };
214
+ if (e.length === 0) {
215
+ this._displayIndexes = this._data.map((n, i) => i).filter(t);
216
+ return;
217
+ }
218
+ const s = this._displayIndexes.filter(t).map((n) => {
219
+ const i = this._data[n];
220
+ return {
221
+ idx: n,
222
+ keys: e.map((o) => i[o.field])
223
+ };
224
+ });
225
+ s.sort((n, i) => {
226
+ for (let o = 0; o < e.length; o++) {
227
+ const l = e[o].dir, r = n.keys[o], a = i.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((n) => n.idx);
241
+ }
242
+ // ─── 필터 ─────────────────────────────────────────────
243
+ applyFilter(e) {
244
+ const t = Object.keys(e);
245
+ this._displayIndexes = this._data.map((s, n) => ({ r: s, i: n })).filter(({ r: s }) => {
246
+ var n;
247
+ if (((n = this._meta.get(s[this._idField])) == null ? void 0 : n.state) === "removed" || t.length > 0 && !t.every((i) => {
248
+ const o = s[i];
249
+ return e[i].every((l) => Ge(o, l));
250
+ }))
251
+ return !1;
252
+ if (this._findQuery && this._findFields.length > 0) {
253
+ const i = this._findQuery;
254
+ if (!this._findFields.some((l) => {
255
+ const r = s[l];
256
+ return r != null && String(r).toLowerCase().includes(i);
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 Ge(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 Qe {
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
+ ), n = t * this.rowHeight;
316
+ return { startIndex: t, endIndex: s, offsetY: n };
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, n = this._scrollTop + this._viewportHeight;
329
+ if (t < this._scrollTop)
330
+ this._scrollTop = t, this.container.scrollTop = t;
331
+ else if (s > n) {
332
+ const i = s - this._viewportHeight;
333
+ this._scrollTop = i, this.container.scrollTop = i;
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 re {
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 = (n, i) => {
355
+ for (const o of n)
356
+ o.children && o.children.length > 0 ? (s(o.children, i + 1), this._maxDepth = Math.max(this._maxDepth, i + 1)) : e.push({ ...o, _colIndex: t++, _depth: i, _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((n) => n.field === e ? !1 : (n.children && (n.children = t(n.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 = (n, i) => {
411
+ let o = 0;
412
+ for (const l of n)
413
+ if (!l.hidden)
414
+ if (l.children && l.children.length > 0) {
415
+ const r = s(l.children, i + 1);
416
+ r > 0 && (e[i - 1].push({
417
+ column: l,
418
+ colIndex: t,
419
+ depth: i,
420
+ colSpan: r,
421
+ rowSpan: 1
422
+ }), o += r);
423
+ } else
424
+ e[i - 1].push({
425
+ column: l,
426
+ colIndex: t++,
427
+ depth: i,
428
+ colSpan: 1,
429
+ rowSpan: this._maxDepth - i + 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, n = s.filter((r) => r.flex), i = s.filter((r) => !r.flex && r.width).reduce((r, a) => r + a.width, 0), o = n.reduce((r, a) => r + (a.flex ?? 1), 0), l = Math.max(0, e - i);
438
+ return s.map((r) => r.flex ? Math.round(r.flex / o * l) : r.width ?? t);
439
+ }
440
+ }
441
+ class Je {
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 n = document.createElement("div");
454
+ n.textContent = "필터", n.style.cssText = "font-weight:600;margin-bottom:8px;color:var(--og-text-color,#333);", this._el.appendChild(n);
455
+ const i = document.createElement("div");
456
+ i.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 w of l) {
471
+ const C = document.createElement("option");
472
+ C.value = w.value, C.textContent = w.label, o.appendChild(C);
473
+ }
474
+ s[0] && (o.value = s[0].operator), i.appendChild(o), this._el.appendChild(i);
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", (w) => {
481
+ w.key === "Enter" ? h.click() : w.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 w = r.value.trim();
499
+ w ? this._onApply(this._field, [{ operator: o.value, value: w }]) : 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 = (w) => {
503
+ !this._el.contains(w.target) && w.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 Ze = 10;
517
+ function et(d, e = Ze) {
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("-"), n = s ? t.slice(1) : t, i = n.indexOf(".");
534
+ let o, l;
535
+ if (i === -1)
536
+ o = BigInt(n), l = 0;
537
+ else {
538
+ const r = n.slice(i + 1);
539
+ o = BigInt(n.slice(0, i) + 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, n] = x._align(this, x.from(e));
556
+ return new x(t + s, n);
557
+ }
558
+ sub(e) {
559
+ const [t, s, n] = x._align(this, x.from(e));
560
+ return new x(t - s, n);
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 i = this._c * 10n ** BigInt(t + s._s) / s._c;
574
+ return new x(i, t + this._s);
575
+ }
576
+ /** 나머지 (정수 나머지와 동일한 개념을 소수에 적용) */
577
+ mod(e) {
578
+ const t = x.from(e), [s, n, i] = x._align(this, t);
579
+ return new x(s % n, i);
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 w = g / c;
629
+ E >= h && (w += 1n), t = u ? -w : w;
630
+ }
631
+ s = e;
632
+ const n = t < 0n, o = (n ? -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 (n ? "-" : "") + 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 tt(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 be(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 ee(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), n = t[6], i = t.length - 7;
788
+ return `${s}-${n}${e.repeat(i)}`;
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)}` : ee(d, e, 3, 4);
793
+ }
794
+ function ot(d, e) {
795
+ const t = d.indexOf("@");
796
+ if (t < 0) return ee(d, e, 2, 0);
797
+ const s = d.slice(0, t), n = d.slice(t), i = Math.min(2, s.length), o = s.slice(0, i), l = Math.max(s.length - i, 3);
798
+ return `${o}${e.repeat(l)}${n}`;
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), n = t.slice(-4), i = t.length - 8, o = e.repeat(Math.max(i, 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(n), l.join("-");
809
+ }
810
+ function lt(d, e, t, s) {
811
+ const n = d.replace(/[^0-9]/g, "");
812
+ if (n.length <= t + s)
813
+ return ee(n, e, t, s);
814
+ const i = n.slice(0, t), o = n.slice(-s), l = n.length - t - s;
815
+ return `${i}-${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 ee(d, e, 3, 0);
824
+ const s = (n) => e.repeat(Math.max(n.length, 3));
825
+ return `${t[0]}.${t[1]}.${s(t[2])}.${s(t[3])}`;
826
+ }
827
+ function ee(d, e, t, s) {
828
+ if (d.length <= t + s) return d;
829
+ const n = d.slice(0, t), i = s > 0 ? d.slice(-s) : "", o = d.length - t - s;
830
+ return `${n}${e.repeat(o)}${i}`;
831
+ }
832
+ function Be(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 = tt(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 = et(s, t)), !e)
848
+ return t != null ? s.toFixed(t) : String(s);
849
+ if (e.includes(",")) {
850
+ const n = e.includes(".") ? e.split(".")[1].length : t ?? 0;
851
+ return s.toLocaleString("ko-KR", {
852
+ minimumFractionDigits: n,
853
+ maximumFractionDigits: n
854
+ });
855
+ }
856
+ return String(s);
857
+ }
858
+ function We(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(), n = String(t.getMonth() + 1).padStart(2, "0"), i = String(t.getDate()).padStart(2, "0");
863
+ return e.replace("yyyy", String(s)).replace("MM", n).replace("dd", i);
864
+ }
865
+ function ht(d, e, t) {
866
+ const s = be(d, e.mask), n = document.createElement("span");
867
+ n.style.cssText = "display:flex;align-items:center;gap:3px;overflow:hidden;width:100%;box-sizing:border-box;";
868
+ const i = document.createElement("span");
869
+ i.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);", i.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(), i.textContent = d, i.style.fontFamily = "", i.style.letterSpacing = "", i.style.color = "", o.remove(), (e._maskRevealedRows ?? (e._maskRevealedRows = /* @__PURE__ */ new Set())).add(t);
877
+ }), n.appendChild(i), n.appendChild(o), n;
878
+ }
879
+ class le {
880
+ render(e) {
881
+ var r;
882
+ const t = document.createElement("span");
883
+ t.className = "og-cell-text";
884
+ const s = Be(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: n, column: i, rowIndex: o } = e;
888
+ let l;
889
+ if (i.valueMap && n != null && i.valueMap[n] ? l = i.valueMap[n] : l = n == null ? "" : String(n), i.mask) {
890
+ const a = i._maskRevealed === !0, c = ((r = i._maskRevealedRows) == null ? void 0 : r.has(o)) === !0;
891
+ if (!a && !c)
892
+ return ht(l, i, 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 n = 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) === n);
909
+ return t.textContent = o ? o.label : n, t;
910
+ }
911
+ }
912
+ class ae {
913
+ render(e) {
914
+ const t = document.createElement("span");
915
+ t.className = "og-cell-number";
916
+ const s = Be(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 de {
921
+ render(e) {
922
+ const t = document.createElement("span");
923
+ return t.className = "og-cell-date", t.textContent = We(e.value, e.column.format), t.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;", t;
924
+ }
925
+ }
926
+ class ce {
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 i, 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${(i = this.def) != null && i.buttonClass ? " " + this.def.buttonClass : ""}`;
944
+ const n = (o = this.def) == null ? void 0 : o.label;
945
+ return typeof n == "function" ? s.textContent = n(e.value, e.row) : s.textContent = n ?? 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"), n = e.value == null ? "" : String(e.value), i = ((l = this.labelMap) == null ? void 0 : l[n]) ?? ((r = e.column.valueMap) == null ? void 0 : r[n]) ?? n;
962
+ s.textContent = i;
963
+ const o = ((a = this.colorMap) == null ? void 0 : a[n]) ?? "#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 _t {
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"), n = (a = this.def) != null && a.srcFn ? this.def.srcFn(e.value, e.row) : String(e.value ?? "");
998
+ s.src = n;
999
+ const i = ((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:${i}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 pt {
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, n = Number(e.value) || 0, i = Math.min(100, Math.max(0, n / s * 100)), o = (c = this.def) != null && c.colorFn ? this.def.colorFn(n) : ((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:${i}%;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(i)}%`, 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 n = ((c = this.def) == null ? void 0 : c.width) ?? 80, i = ((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 = n, r.height = i, r.style.cssText = "display:block;";
1038
+ const a = r.getContext("2d");
1039
+ if (a) {
1040
+ const E = Math.max(...s, 1), w = Math.min(...s, 0), C = E - w || 1, M = s.length;
1041
+ if (l === "bar") {
1042
+ const p = n / M;
1043
+ s.forEach((v, _) => {
1044
+ const F = (v - w) / C * (i - 2);
1045
+ a.fillStyle = o, a.fillRect(_ * p + 1, i - F - 1, p - 2, F);
1046
+ });
1047
+ } else {
1048
+ const p = s.map((v, _) => ({
1049
+ x: _ / (M - 1 || 1) * n,
1050
+ y: i - (v - w) / C * (i - 4) - 2
1051
+ }));
1052
+ l === "area" && (a.fillStyle = o + "33", a.beginPath(), a.moveTo(p[0].x, i), p.forEach((v) => a.lineTo(v.x, v.y)), a.lineTo(p[p.length - 1].x, i), a.closePath(), a.fill()), a.strokeStyle = o, a.lineWidth = 1.5, a.beginPath(), p.forEach((v, _) => _ === 0 ? a.moveTo(v.x, v.y) : a.lineTo(v.x, v.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, n = document.createElement("span");
1063
+ n.className = "og-switch" + (s ? " og-switch--on" : ""), n.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 i = document.createElement("span");
1067
+ return i.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);`, n.appendChild(i), t.appendChild(n), 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, n = Math.round(Number(e.value) || 0), i = ((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 <= n ? i : "#e0e0e0"};line-height:1;`, t.appendChild(a);
1084
+ }
1085
+ return t;
1086
+ }
1087
+ }
1088
+ class he {
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 ue {
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 wt(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 ge {
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, n = String(e.value ?? "");
1120
+ return t.innerHTML = s ? wt(n) : n, t;
1121
+ }
1122
+ }
1123
+ const yt = [
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
+ ], bt = "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 n = s.charCodeAt(0) - 32;
1255
+ n >= 0 && n <= 94 && e.push(n);
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(yt[s])).join("") + Le(bt) + "11";
1260
+ }
1261
+ class _e {
1262
+ render(e) {
1263
+ const t = String(e.value ?? ""), s = e.column.barcodeHeight ?? 28, n = document.createElement("div");
1264
+ n.style.cssText = "display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;overflow:hidden;gap:1px;", n.setAttribute("role", "img"), n.setAttribute("aria-label", `바코드: ${t}`), n.innerHTML = xt(t, s);
1265
+ const i = document.createElement("span");
1266
+ return i.textContent = t, i.style.cssText = "font-size:9px;font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;", n.appendChild(i), n;
1267
+ }
1268
+ }
1269
+ function xt(d, e) {
1270
+ if (!d) return "";
1271
+ const t = vt(d), s = 1.4, n = 6, i = t.length * s + n * 2, o = [];
1272
+ let l = 0, r = n;
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 ${i.toFixed(2)} ${e}" width="${i.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 ae();
1288
+ case "date":
1289
+ return new de();
1290
+ case "boolean":
1291
+ return new ce();
1292
+ case "radio":
1293
+ return new he();
1294
+ case "img":
1295
+ return new ue();
1296
+ case "html":
1297
+ return new ge();
1298
+ case "barcode":
1299
+ return new _e();
1300
+ case "select":
1301
+ return new ut(d.options ?? [], d.optionsFn);
1302
+ default:
1303
+ return new le();
1304
+ }
1305
+ if (typeof e == "string")
1306
+ switch (e) {
1307
+ case "number":
1308
+ return new ae();
1309
+ case "date":
1310
+ return new de();
1311
+ case "checkbox":
1312
+ return new ce();
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 he();
1323
+ case "img":
1324
+ return new ue();
1325
+ case "html":
1326
+ return new ge();
1327
+ case "barcode":
1328
+ return new _e();
1329
+ default:
1330
+ return new le();
1331
+ }
1332
+ switch (e.type) {
1333
+ case "button":
1334
+ return new Re(e);
1335
+ case "checkbox":
1336
+ return new ce();
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 _t(e);
1345
+ case "progress":
1346
+ return new pt(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 ae();
1355
+ case "date":
1356
+ return new de();
1357
+ case "radio":
1358
+ return new he();
1359
+ case "img":
1360
+ return new ue();
1361
+ case "html":
1362
+ return new ge();
1363
+ case "barcode":
1364
+ return new _e();
1365
+ default:
1366
+ return new le();
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 = S("div", "og-header"), this._header.style.cssText = "flex-shrink:0;overflow-x:auto;overflow-y:hidden;border-bottom:1px solid var(--og-border-color,#e0e0e0);scrollbar-width:none;", this._bodyWrap = S("div", "og-body-wrapper"), this._bodyWrap.style.cssText = "flex:1;overflow:auto;position:relative;", this._bodyWrap.style.setProperty("--scrollbar-size", "8px"), this._body = S("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, n, i) {
1382
+ var g, E;
1383
+ this._header.innerHTML = "";
1384
+ const o = i._frozenCount ?? 0;
1385
+ let l = 0;
1386
+ i.stateColumn && (l += 24), i.draggable && (l += 18), i.rowNumber && (l += 44), i.checkColumn && (l += 36);
1387
+ const r = l + t.reduce((w, C, M) => w + (s[M] ?? i.defaultColumnWidth), 0);
1388
+ this._header.style.background = "var(--og-header-bg,#f5f5f5)";
1389
+ const a = S("table");
1390
+ a.setAttribute("role", "presentation"), a.style.cssText = `table-layout:fixed;border-collapse:collapse;width:${r}px;background:var(--og-header-bg,#f5f5f5);`;
1391
+ const c = e.length;
1392
+ let h = 0;
1393
+ const u = (w, C, M, p = "") => {
1394
+ const v = S("th", `og-header-cell og-extra-col ${p}`);
1395
+ v.setAttribute("rowspan", String(c)), v.textContent = M, Te(v, {
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
+ padding: "0",
1402
+ fontSize: "11px",
1403
+ color: "#999",
1404
+ userSelect: "none",
1405
+ boxSizing: "border-box",
1406
+ background: "var(--og-header-bg,#f5f5f5)"
1407
+ }), o > 0 && (v.style.position = "sticky", v.style.left = `${h}px`, v.style.zIndex = "4"), h += C, w.appendChild(v);
1408
+ };
1409
+ for (let w = 0; w < e.length; w++) {
1410
+ const C = S("tr", "og-header-row");
1411
+ if (C.style.height = `${i.headerHeight}px`, w === 0 && (i.stateColumn && u(C, 24, ""), i.draggable && u(C, 18, ""), i.rowNumber && u(C, 44, "No"), i.checkColumn)) {
1412
+ const M = S("th", "og-header-cell og-extra-col");
1413
+ 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);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;
1414
+ const p = document.createElement("input");
1415
+ p.type = "checkbox", p.setAttribute("aria-label", "전체 행 선택"), p.style.cssText = "width:16px;height:16px;", p.addEventListener("change", () => this._cbs.onAllCheck(p.checked)), M.appendChild(p), C.appendChild(M);
1416
+ }
1417
+ for (const M of e[w] ?? []) {
1418
+ const p = S("th", "og-header-cell"), v = M.column;
1419
+ M.colSpan > 1 && (p.colSpan = M.colSpan), M.rowSpan > 1 && (p.rowSpan = M.rowSpan);
1420
+ const _ = M.colSpan === 1 ? t.findIndex((m) => m.field === v.field) : -1;
1421
+ if (M.colSpan === 1) {
1422
+ const m = _ >= 0 ? s[_] ?? i.defaultColumnWidth : v.width ?? i.defaultColumnWidth;
1423
+ p.style.width = `${m}px`, p.style.minWidth = `${m}px`;
1424
+ }
1425
+ const F = n.find((m) => m.field === v.field), A = v.sortable !== !1 && i.sortable && M.colSpan === 1;
1426
+ if (p.setAttribute("role", "columnheader"), p.setAttribute("scope", "col"), A && (p.setAttribute("aria-sort", F ? F.dir === "asc" ? "ascending" : "descending" : "none"), p.tabIndex = _ === 0 ? 0 : -1, p.addEventListener("keydown", (m) => {
1427
+ if (m.key === "Enter" || m.key === " ")
1428
+ m.preventDefault(), this._cbs.onHeaderClick(v.field, m.shiftKey);
1429
+ else if (m.key === "ArrowRight") {
1430
+ m.preventDefault();
1431
+ const b = p.nextElementSibling;
1432
+ (b == null ? void 0 : b.tagName) === "TH" && b.focus();
1433
+ } else if (m.key === "ArrowLeft") {
1434
+ m.preventDefault();
1435
+ const b = p.previousElementSibling;
1436
+ (b == null ? void 0 : b.tagName) === "TH" && b.focus();
1437
+ }
1438
+ })), _ >= 0 && _ < o) {
1439
+ let m = 0;
1440
+ i.stateColumn && (m += 24), i.draggable && (m += 18), i.rowNumber && (m += 44), i.checkColumn && (m += 36);
1441
+ for (let b = 0; b < _; b++) m += s[b] ?? i.defaultColumnWidth;
1442
+ p.classList.add("og-frozen"), _ === o - 1 && p.classList.add("og-frozen-last"), p.style.left = `${m}px`;
1443
+ }
1444
+ Te(p, {
1445
+ padding: "4px 8px",
1446
+ boxSizing: "border-box",
1447
+ textAlign: v.headerAlign ?? "center",
1448
+ borderRight: "1px solid var(--og-border-color,#e0e0e0)",
1449
+ borderBottom: "1px solid var(--og-border-color,#e0e0e0)",
1450
+ userSelect: "none",
1451
+ cursor: A ? "pointer" : "default",
1452
+ whiteSpace: "nowrap",
1453
+ overflow: "hidden",
1454
+ textOverflow: "ellipsis",
1455
+ position: "relative"
1456
+ });
1457
+ const H = S("span");
1458
+ if (H.textContent = v.header ?? v.field, H.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;", p.appendChild(H), F) {
1459
+ p.classList.add("og-sorted");
1460
+ const m = S("span", "og-sort-icon");
1461
+ m.textContent = F.dir === "asc" ? " ↑" : " ↓", p.appendChild(m);
1462
+ }
1463
+ if (v.filterable !== !1 && i.filterable && M.colSpan === 1) {
1464
+ const m = S("span", "og-filter-icon"), b = ((E = (g = i._activeFilters) == null ? void 0 : g[v.field]) == null ? void 0 : E.length) > 0;
1465
+ m.textContent = b ? "⊿" : "▿", m.title = "필터", m.style.cssText = "margin-left:3px;cursor:pointer;font-size:10px;opacity:0.6;", b && m.classList.add("og-filter-icon--active"), m.addEventListener("click", (k) => {
1466
+ k.stopPropagation(), this._cbs.onFilterIconClick(v.field, m);
1467
+ }), p.appendChild(m);
1468
+ }
1469
+ if (v.resizable !== !1) {
1470
+ const m = S("div", "og-resize-handle");
1471
+ m.style.cssText = "position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1;", p.appendChild(m);
1472
+ const b = _;
1473
+ Rt(m, p, (k) => {
1474
+ b >= 0 && this._cbs.onColResize(b, k);
1475
+ });
1476
+ }
1477
+ i.columnReorder && _ >= 0 && M.colSpan === 1 && (p.draggable = !0, p.addEventListener("dragstart", (m) => {
1478
+ var b;
1479
+ this._cbs.onColDragStart(_), p.classList.add("og-col-dragging"), (b = m.dataTransfer) == null || b.setData("text/plain", String(_));
1480
+ }), p.addEventListener("dragend", () => {
1481
+ p.classList.remove("og-col-dragging"), this._header.querySelectorAll(".og-col-drop-over").forEach((m) => m.classList.remove("og-col-drop-over"));
1482
+ }), p.addEventListener("dragover", (m) => {
1483
+ m.preventDefault();
1484
+ const b = this._cbs.getColDragIdx();
1485
+ b !== null && b !== _ && (this._header.querySelectorAll(".og-col-drop-over").forEach((k) => k.classList.remove("og-col-drop-over")), p.classList.add("og-col-drop-over"));
1486
+ }), p.addEventListener("dragleave", () => {
1487
+ p.classList.remove("og-col-drop-over");
1488
+ }), p.addEventListener("drop", (m) => {
1489
+ m.preventDefault(), p.classList.remove("og-col-drop-over"), this._cbs.onColDrop(_);
1490
+ })), A && p.addEventListener("click", (m) => {
1491
+ m.target.classList.contains("og-resize-handle") || this._cbs.onHeaderClick(v.field, m.shiftKey);
1492
+ }), C.appendChild(p);
1493
+ }
1494
+ a.appendChild(C);
1495
+ }
1496
+ this._header.appendChild(a);
1497
+ }
1498
+ renderBody(e, t, s, n, i, o, l, r, a, c, h = null, u, g, E = {}, w) {
1499
+ var p, v;
1500
+ Object.keys(E).length && (o = { ...o, ...E }), this._body.innerHTML = "", this._cellMap.clear(), this._body.style.height = `${r}px`;
1501
+ const C = o._frozenCount ?? 0;
1502
+ {
1503
+ let _ = 0;
1504
+ o.stateColumn && (_ += 24), o.draggable && (_ += 18), o.rowNumber && (_ += 44), o.checkColumn && (_ += 36);
1505
+ const F = _ + n.reduce((A, H, $) => A + (i[$] ?? o.defaultColumnWidth), 0);
1506
+ this._body.style.minWidth = `${F}px`;
1507
+ }
1508
+ if (t < e) return;
1509
+ const M = document.createDocumentFragment();
1510
+ for (let _ = e; _ <= t; _++) {
1511
+ const F = h ? h[_] : null, A = F && F._isGroup === !0, H = F && F._isTree === !0;
1512
+ if (A) {
1513
+ const f = F, L = `__${f._groupField}:${f._groupValue}`, D = S("div", "og-group-row"), te = l + (_ - e) * o.rowHeight;
1514
+ D.style.cssText = [
1515
+ `top:${te}px;height:${o.rowHeight}px;`,
1516
+ "display:flex;align-items:stretch;cursor:pointer;",
1517
+ `padding-left:${4 + f._depth * 12}px;`,
1518
+ "background:var(--og-header-bg,#f5f5f5);",
1519
+ "border-bottom:1px solid var(--og-border-color,#e0e0e0);"
1520
+ ].join(""), D.setAttribute("role", "row"), D.setAttribute("aria-expanded", f._expanded ? "true" : "false"), D.setAttribute("aria-rowindex", String(_ + 1)), D.setAttribute("aria-level", String(f._depth + 1));
1521
+ let P = 0;
1522
+ if (o.stateColumn && (P += 24), o.draggable && (P += 18), o.rowNumber && (P += 44), o.checkColumn && (P += 36), P > 0) {
1523
+ const y = S("div", "og-group-state-cell");
1524
+ y.style.cssText = [
1525
+ `width:${P}px;min-width:${P}px;flex-shrink:0;`,
1526
+ "display:flex;align-items:center;justify-content:center;",
1527
+ "font-size:10px;font-weight:700;gap:2px;",
1528
+ "border-right:1px solid var(--og-border-color,#e0e0e0);"
1529
+ ].join("");
1530
+ const I = f._states ?? { added: 0, edited: 0, removed: 0 };
1531
+ if (I.added > 0) {
1532
+ const z = S("span");
1533
+ z.textContent = `+${I.added}`, z.style.cssText = "color:var(--og-row-added-bg,#2e7d32);background:#e8f5e9;padding:1px 3px;border-radius:3px;", y.appendChild(z);
1534
+ }
1535
+ if (I.edited > 0) {
1536
+ const z = S("span");
1537
+ z.textContent = `M${I.edited}`, z.style.cssText = "color:#e65100;background:#fff8e1;padding:1px 3px;border-radius:3px;", y.appendChild(z);
1538
+ }
1539
+ if (I.removed > 0) {
1540
+ const z = S("span");
1541
+ z.textContent = `D${I.removed}`, z.style.cssText = "color:var(--og-row-removed-bg,#c62828);background:#ffebee;padding:1px 3px;border-radius:3px;", y.appendChild(z);
1542
+ }
1543
+ D.appendChild(y);
1544
+ }
1545
+ let O = !1;
1546
+ for (let y = 0; y < n.length; y++) {
1547
+ const I = n[y], z = i[y] ?? o.defaultColumnWidth, se = f._summaryFmt !== void 0 && I.field in (f._summaryFmt ?? {}), B = S("div", "og-group-cell");
1548
+ if (B.style.cssText = [
1549
+ `width:${z}px;min-width:${z}px;flex-shrink:0;`,
1550
+ "padding:2px 8px;box-sizing:border-box;overflow:hidden;",
1551
+ "border-right:1px solid var(--og-border-color,#e0e0e0);",
1552
+ "display:flex;align-items:center;",
1553
+ "white-space:nowrap;text-overflow:ellipsis;"
1554
+ ].join(""), se) {
1555
+ const U = f._summaryFmt[I.field];
1556
+ B.textContent = U !== "" ? U : "-", B.style.justifyContent = "flex-end", B.style.color = "var(--og-primary,#1976d2)", B.style.fontWeight = "600";
1557
+ } else if (!O) {
1558
+ O = !0;
1559
+ const U = S("span", "og-group-arrow");
1560
+ U.textContent = f._expanded ? "▾ " : "▸ ", U.style.cssText = "color:var(--og-primary,#1976d2);margin-right:4px;flex-shrink:0;", B.appendChild(U);
1561
+ const j = S("span", "og-group-label");
1562
+ j.textContent = `${f._groupLabel} (${f._childCount}건)`, j.style.cssText = "overflow:hidden;text-overflow:ellipsis;font-weight:600;", B.appendChild(j), B.style.gap = "0";
1563
+ }
1564
+ D.appendChild(B);
1565
+ }
1566
+ D.addEventListener("click", () => u == null ? void 0 : u(L)), M.appendChild(D);
1567
+ continue;
1568
+ }
1569
+ const $ = H ? F : null, m = $ ? $.data : h ? F : s.getRowByIndex(_);
1570
+ if (!m) continue;
1571
+ const b = H || A ? "none" : s.getRowState(_), k = S("div", "og-row");
1572
+ k.setAttribute("role", "row"), k.setAttribute("aria-rowindex", String(_ + 1));
1573
+ const K = l + (_ - e) * o.rowHeight;
1574
+ k.style.top = `${K}px`, k.style.height = `${o.rowHeight}px`;
1575
+ let T = _ % 2 === 0 ? "var(--og-row-bg,#fff)" : "var(--og-row-alt-bg,#fafafa)";
1576
+ k.style.background = T, b === "added" && k.classList.add("og-state-added"), b === "edited" && k.classList.add("og-state-edited"), b === "removed" && k.classList.add("og-state-removed"), a.has(_) && k.classList.add("og-selected"), k.setAttribute("aria-selected", a.has(_) ? "true" : "false"), b === "added" && (T = "var(--og-row-added-bg,#e8f5e9)"), b === "edited" && (T = "var(--og-row-edited-bg,#fff8e1)"), b === "removed" && (T = "var(--og-row-removed-bg,#ffebee)"), a.has(_) && (T = "var(--og-row-selected-bg,#bbdefb)");
1577
+ const ne = _;
1578
+ k.addEventListener("click", (f) => {
1579
+ this._cbs.onCellClick(ne, -1, f);
1580
+ });
1581
+ const oe = /* @__PURE__ */ new Map();
1582
+ let V = 0;
1583
+ if (o.stateColumn) {
1584
+ const f = S("div", "og-cell og-col-state"), L = { added: "✚", edited: "✎", removed: "✖", none: "" }, D = { added: "#2e7d32", edited: "#bf360c", removed: "#c62828", none: "" };
1585
+ f.textContent = L[b] ?? "", f.style.color = D[b] ?? "", f.title = b, C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = T), V += 24, k.appendChild(f);
1586
+ }
1587
+ const J = this._cbs.getDndManager();
1588
+ if (o.draggable && J) {
1589
+ const f = J.attachHandle(k, _, o._totalRows ?? t + 1);
1590
+ C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = T), V += 18, k.appendChild(f);
1591
+ }
1592
+ if (o.rowNumber) {
1593
+ const f = S("div", "og-cell og-col-rownum");
1594
+ f.textContent = String(_ + 1), C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = T), V += 44, k.appendChild(f);
1595
+ }
1596
+ if (o.checkColumn) {
1597
+ const f = S("div", "og-cell og-col-check"), L = document.createElement("input");
1598
+ L.type = "checkbox", L.checked = c.has(_), L.setAttribute("aria-label", `${_ + 1}행 선택`), L.addEventListener("click", (D) => D.stopPropagation()), L.addEventListener("change", (D) => {
1599
+ D.stopPropagation(), this._cbs.onRowCheck(_, L.checked);
1600
+ }), f.appendChild(L), C > 0 && (f.style.position = "sticky", f.style.left = `${V}px`, f.style.zIndex = "2", f.style.background = T), V += 36, k.appendChild(f);
1601
+ }
1602
+ for (let f = 0; f < n.length; f++) {
1603
+ const L = n[f], D = i[f] ?? o.defaultColumnWidth, te = o.editable && L.editable !== !1, P = f === 0, O = w && !w.isEmpty ? w.getInfo(_, f) : null;
1604
+ if (O != null && O.hidden) {
1605
+ const R = S("div", "og-cell og-cell--merge-ph");
1606
+ R.style.cssText = `width:${D}px;min-width:${D}px;flex-shrink:0;visibility:hidden;box-sizing:border-box;`, k.appendChild(R);
1607
+ continue;
1608
+ }
1609
+ const y = S("div", "og-cell");
1610
+ y.setAttribute("role", "gridcell"), y.setAttribute("aria-colindex", String(f + 1));
1611
+ const I = (O == null ? void 0 : O.rowSpan) ?? 1, z = (O == null ? void 0 : O.colSpan) ?? 1, se = I > 1 ? I * o.rowHeight : o.rowHeight;
1612
+ let B = D;
1613
+ if (z > 1)
1614
+ for (let R = 1; R < z; R++)
1615
+ B += i[f + R] ?? o.defaultColumnWidth;
1616
+ const U = f < C;
1617
+ let j = 0;
1618
+ if (U) {
1619
+ o.stateColumn && (j += 24), o.draggable && (j += 18), o.rowNumber && (j += 44), o.checkColumn && (j += 36);
1620
+ for (let R = 0; R < f; R++) j += i[R] ?? o.defaultColumnWidth;
1621
+ y.classList.add("og-frozen-cell"), f === C - 1 && y.classList.add("og-frozen-last");
1622
+ }
1623
+ y.style.width = `${B}px`, y.style.minWidth = `${B}px`, y.style.maxWidth = `${B}px`, I > 1 && (y.style.height = `${se}px`), U && (y.style.background = T), $ && P && (y.style.padding = "0"), y.style.overflow = "hidden", I > 1 ? (y.style.height = `${se}px`, y.style.position = "absolute", y.style.zIndex = "3", y.style.background = T && T !== "inherit" ? T : "var(--og-row-bg, #fff)", y.style.borderBottom = "1px solid var(--og-border-color, #e0e0e0)") : U && (y.style.position = "sticky", y.style.left = `${j}px`, y.style.zIndex = "1"), L.type === "number" || L.align === "right" ? y.classList.add("og-cell--right") : L.align === "center" && y.classList.add("og-cell--center"), te && y.classList.add("og-cell--editable"), te || y.setAttribute("aria-readonly", "true"), z > 1 && y.setAttribute("aria-colspan", String(z)), I > 1 && y.setAttribute("aria-rowspan", String(I)), ((p = o._focusCell) == null ? void 0 : p.ri) === _ && ((v = o._focusCell) == null ? void 0 : v.ci) === f && (y.classList.add("og-cell-focused"), y.tabIndex = -1);
1624
+ const xe = m ? m[L.field] : null;
1625
+ y.setAttribute("aria-label", `${L.header}: ${xe == null ? "" : String(xe)}`);
1626
+ let Ce = y;
1627
+ if ($ && P) {
1628
+ const R = S("div", "og-tree-cell"), q = $._ancestorHasMore ?? [];
1629
+ for (let N = 0; N < $._depth; N++) {
1630
+ const Y = S("span", "og-tree-guide");
1631
+ q[N] && Y.classList.add("og-tree-guide--line"), R.appendChild(Y);
1632
+ }
1633
+ if ($._depth > 0) {
1634
+ const N = S("span", "og-tree-connector");
1635
+ N.classList.add(
1636
+ $._isLastChild ? "og-tree-connector--last" : "og-tree-connector--mid"
1637
+ ), R.appendChild(N);
1638
+ }
1639
+ const ie = S("span", "og-tree-toggle-wrap");
1640
+ if (!$._hasChildren) {
1641
+ const N = S("span", "og-tree-leaf-dot");
1642
+ ie.appendChild(N);
1643
+ }
1644
+ R.appendChild(ie);
1645
+ const W = document.createElement("i");
1646
+ if ($._hasChildren) {
1647
+ const N = Fe(L.treeNodeIcon, m, !0, $._expanded);
1648
+ W.className = $._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", $._expanded ? "true" : "false"), W.setAttribute("aria-label", $._expanded ? "접기" : "펼치기"), W.addEventListener("click", (Y) => {
1649
+ Y.stopPropagation(), g == null || g($._treeId);
1650
+ }), W.addEventListener("keydown", (Y) => {
1651
+ (Y.key === "Enter" || Y.key === " ") && (Y.preventDefault(), Y.stopPropagation(), g == null || g($._treeId));
1652
+ });
1653
+ } else {
1654
+ const N = Fe(L.treeNodeIcon, m, !1, !1);
1655
+ W.setAttribute("aria-hidden", "true"), W.className = `${N} og-tree-node-icon og-tree-node-icon--leaf`;
1656
+ }
1657
+ R.appendChild(W), y.appendChild(R), Ce = R;
1658
+ }
1659
+ if (L.cellStyle) {
1660
+ const R = m[L.field], q = typeof L.cellStyle == "function" ? L.cellStyle(R, m, _) : L.cellStyle;
1661
+ Object.assign(y.style, q);
1662
+ }
1663
+ const je = Ct(L).render({
1664
+ value: m[L.field],
1665
+ row: m,
1666
+ rowIndex: _,
1667
+ column: L,
1668
+ colIndex: f,
1669
+ isSelected: a.has(_),
1670
+ rowState: b
1671
+ });
1672
+ Ce.appendChild(je);
1673
+ const X = _, G = f;
1674
+ if (y.addEventListener("click", (R) => {
1675
+ R.stopPropagation(), this._cbs.onCellClick(X, G, R);
1676
+ }), y.addEventListener("dblclick", (R) => {
1677
+ R.stopPropagation(), this._cbs.onCellDblClick(X, G, R);
1678
+ }), y.addEventListener("mouseover", (R) => {
1679
+ R.stopPropagation(), this._cbs.onCellMouseOver(X, G, R);
1680
+ }), y.addEventListener("mouseout", (R) => {
1681
+ R.stopPropagation(), this._cbs.onCellMouseOut(X, G, R);
1682
+ }), y.addEventListener("mousedown", (R) => {
1683
+ R.stopPropagation(), this._cbs.onCellMouseDown(X, G, R);
1684
+ }), y.addEventListener("mouseup", (R) => {
1685
+ R.stopPropagation(), this._cbs.onCellMouseUp(X, G, R);
1686
+ }), y.addEventListener("mousemove", (R) => {
1687
+ R.stopPropagation(), this._cbs.onCellMouseMove(X, G, R);
1688
+ }), oe.set(f, y), I > 1) {
1689
+ const R = document.createElement("div");
1690
+ R.style.cssText = [
1691
+ `width:${D}px;min-width:${D}px;height:${o.rowHeight}px;`,
1692
+ "flex-shrink:0;box-sizing:border-box;",
1693
+ "border-right:1px solid var(--og-border-color,#e0e0e0);"
1694
+ ].join(""), k.appendChild(R);
1695
+ let q = 0;
1696
+ o.stateColumn && (q += 24), o.draggable && (q += 18), o.rowNumber && (q += 44), o.checkColumn && (q += 36);
1697
+ for (let W = 0; W < f; W++) q += i[W] ?? o.defaultColumnWidth;
1698
+ const ie = l + (_ - e) * o.rowHeight;
1699
+ y.style.left = `${q}px`, y.style.top = `${ie}px`, M.appendChild(y);
1700
+ } else
1701
+ k.appendChild(y);
1702
+ }
1703
+ this._cellMap.set(_, oe), M.appendChild(k);
1704
+ }
1705
+ if (s.rowCount === 0) {
1706
+ const _ = S("div", "og-empty-message");
1707
+ _.textContent = "데이터가 없습니다.", _.style.cssText = "width:100%;", M.appendChild(_);
1708
+ }
1709
+ this._body.appendChild(M);
1710
+ }
1711
+ getCellEl(e, t) {
1712
+ var s;
1713
+ return (s = this._cellMap.get(e)) == null ? void 0 : s.get(t);
1714
+ }
1715
+ destroy() {
1716
+ this._root.innerHTML = "";
1717
+ }
1718
+ }
1719
+ function Fe(d, e, t, s) {
1720
+ let n;
1721
+ return d ? typeof d == "function" ? n = d(e, t, s) : t ? n = s ? d.branchOpen ?? "bi-folder2-open" : d.branch ?? "bi-folder2" : n = d.leaf ?? "bi-file-earmark" : n = t ? s ? "bi-folder2-open" : "bi-folder2" : "bi-file-earmark", n.startsWith("bi ") ? n : `bi ${n}`;
1722
+ }
1723
+ function S(d, e) {
1724
+ const t = document.createElement(d);
1725
+ return e && (t.className = e), t;
1726
+ }
1727
+ function Te(d, e) {
1728
+ Object.assign(d.style, e);
1729
+ }
1730
+ function De(d, e, t = "text/plain;charset=utf-8") {
1731
+ const s = new Blob([d], { type: t }), n = URL.createObjectURL(s), i = document.createElement("a");
1732
+ i.href = n, i.download = e, i.click(), URL.revokeObjectURL(n);
1733
+ }
1734
+ function Rt(d, e, t) {
1735
+ let s = 0, n = 0;
1736
+ d.addEventListener("mousedown", (i) => {
1737
+ i.stopPropagation(), i.preventDefault(), s = i.clientX, n = e.offsetWidth;
1738
+ const o = (r) => {
1739
+ const a = Math.max(40, n + r.clientX - s);
1740
+ e.style.width = `${a}px`, e.style.minWidth = `${a}px`;
1741
+ }, l = (r) => {
1742
+ document.removeEventListener("mousemove", o), document.removeEventListener("mouseup", l), t(Math.max(40, n + r.clientX - s));
1743
+ };
1744
+ document.addEventListener("mousemove", o), document.addEventListener("mouseup", l);
1745
+ });
1746
+ }
1747
+ class kt {
1748
+ constructor(e) {
1749
+ this._selectedRows = /* @__PURE__ */ new Set(), this._checkedRows = /* @__PURE__ */ new Set(), this._data = e;
1750
+ }
1751
+ // ─── Read-only 접근 ───────────────────────────────────────
1752
+ get selectedRows() {
1753
+ return this._selectedRows;
1754
+ }
1755
+ get checkedRows() {
1756
+ return this._checkedRows;
1757
+ }
1758
+ // ─── 선택 변경 ───────────────────────────────────────────
1759
+ selectSingle(e) {
1760
+ this._selectedRows.clear(), this._selectedRows.add(e);
1761
+ }
1762
+ selectToggle(e) {
1763
+ this._selectedRows.has(e) ? this._selectedRows.delete(e) : this._selectedRows.add(e);
1764
+ }
1765
+ clearSelection() {
1766
+ this._selectedRows.clear();
1767
+ }
1768
+ // ─── 체크 변경 ───────────────────────────────────────────
1769
+ check(e, t) {
1770
+ t ? this._checkedRows.add(e) : this._checkedRows.delete(e);
1771
+ }
1772
+ checkAll(e, t) {
1773
+ if (e)
1774
+ for (let s = 0; s < t; s++) this._checkedRows.add(s);
1775
+ else
1776
+ this._checkedRows.clear();
1777
+ }
1778
+ checkByValue(e, t) {
1779
+ for (let s = 0; s < this._data.rowCount; s++)
1780
+ t.includes(this._data.getCellValue(s, e)) && this._checkedRows.add(s);
1781
+ }
1782
+ uncheckAll() {
1783
+ this._checkedRows.clear();
1784
+ }
1785
+ checkById(e) {
1786
+ }
1787
+ addCheckById(e) {
1788
+ }
1789
+ uncheckById(e) {
1790
+ }
1791
+ // ─── 선택 쿼리 API ───────────────────────────────────────
1792
+ getSelections() {
1793
+ return [...this._selectedRows].map((e) => this._data.getRowByIndex(e)).filter(Boolean);
1794
+ }
1795
+ getChecked() {
1796
+ return [...this._checkedRows].map((e) => ({
1797
+ row: this._data.getRowByIndex(e),
1798
+ rowIndex: e
1799
+ }));
1800
+ }
1801
+ getAllChecked() {
1802
+ return this.getChecked().map((e) => e.row);
1803
+ }
1804
+ getActiveRow() {
1805
+ return this._selectedRows.size > 0 ? [...this._selectedRows][0] : -1;
1806
+ }
1807
+ activate(e) {
1808
+ this._selectedRows.clear(), this._selectedRows.add(e);
1809
+ }
1810
+ deselect() {
1811
+ this._selectedRows.clear();
1812
+ }
1813
+ // ─── 전체 초기화 (setData / clearData 시) ────────────────
1814
+ reset() {
1815
+ this._selectedRows.clear(), this._checkedRows.clear();
1816
+ }
1817
+ }
1818
+ class pe {
1819
+ constructor() {
1820
+ this._onKeyDown = (e) => {
1821
+ e.stopPropagation(), e.key === "Enter" ? (e.preventDefault(), this._onCommit(this.input.value)) : e.key === "Escape" && this._onCancel();
1822
+ }, this._onBlur = () => {
1823
+ this._onCommit(this.input.value);
1824
+ };
1825
+ }
1826
+ mount(e, t, s, n) {
1827
+ this._container = e, this._onCommit = s, this._onCancel = n, 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 ?? "날짜 선택");
1828
+ const i = t.value;
1829
+ if (i) {
1830
+ const o = i instanceof Date ? i : new Date(i);
1831
+ isNaN(o.getTime()) || (this.input.value = We(o, "yyyy-MM-dd"));
1832
+ }
1833
+ this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1834
+ }
1835
+ getValue() {
1836
+ var e;
1837
+ return (e = this.input) == null ? void 0 : e.value;
1838
+ }
1839
+ focus() {
1840
+ var e;
1841
+ (e = this.input) == null || e.focus();
1842
+ }
1843
+ destroy() {
1844
+ var e, t, s;
1845
+ (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);
1846
+ }
1847
+ }
1848
+ function $e(d) {
1849
+ return d.map((e) => typeof e == "string" ? { label: e, value: e } : { label: e.label ?? e.text ?? String(e.value ?? ""), value: e.value });
1850
+ }
1851
+ class fe {
1852
+ constructor(e = [], t) {
1853
+ this._options = $e(e), this._optionsFn = t ?? null;
1854
+ }
1855
+ mount(e, t, s, n) {
1856
+ this._container = e, this._onCommit = s, this._onCancel = n, 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 ?? "선택");
1857
+ const i = this._optionsFn ? $e(this._optionsFn(t.row, t.rowIndex)) : this._options;
1858
+ for (const l of i) {
1859
+ const r = document.createElement("option");
1860
+ r.value = String(l.value), r.textContent = l.label, this.select.appendChild(r);
1861
+ }
1862
+ const o = t.value == null ? "" : String(t.value);
1863
+ i.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) => {
1864
+ l.key === "Escape" && n();
1865
+ }), e.appendChild(this.select);
1866
+ }
1867
+ getValue() {
1868
+ var e;
1869
+ return (e = this.select) == null ? void 0 : e.value;
1870
+ }
1871
+ focus() {
1872
+ var e;
1873
+ (e = this.select) == null || e.focus();
1874
+ }
1875
+ destroy() {
1876
+ var e;
1877
+ (e = this._container) == null || e.setAttribute("aria-expanded", "false");
1878
+ }
1879
+ }
1880
+ class me {
1881
+ constructor() {
1882
+ this._onKeyDown = (e) => {
1883
+ e.stopPropagation(), e.key === "Enter" || e.key === "Tab" ? (e.preventDefault(), this._onCommit(this.input.value)) : e.key === "Escape" && this._onCancel();
1884
+ }, this._onBlur = () => {
1885
+ this._onCommit(this.input.value);
1886
+ };
1887
+ }
1888
+ mount(e, t, s, n) {
1889
+ this._onCommit = s, this._onCancel = n, this.input = document.createElement("input"), this.input.type = "text", this.input.value = t.value == null ? "" : String(t.value), this.input.style.cssText = `
1890
+ width:100%;height:100%;border:none;outline:none;padding:0 8px;
1891
+ font-size:var(--og-font-size,13px);font-family:var(--og-font-family,sans-serif);
1892
+ background:var(--og-row-bg,#fff);box-sizing:border-box;
1893
+ `, this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1894
+ }
1895
+ getValue() {
1896
+ var e;
1897
+ return (e = this.input) == null ? void 0 : e.value;
1898
+ }
1899
+ focus() {
1900
+ var e, t;
1901
+ (e = this.input) == null || e.focus(), (t = this.input) == null || t.select();
1902
+ }
1903
+ destroy() {
1904
+ var e, t;
1905
+ (e = this.input) == null || e.removeEventListener("keydown", this._onKeyDown), (t = this.input) == null || t.removeEventListener("blur", this._onBlur);
1906
+ }
1907
+ }
1908
+ class we {
1909
+ constructor(e) {
1910
+ this._onKeyDown = (t) => {
1911
+ t.stopPropagation(), t.key === "Enter" || t.key === "Tab" ? (t.preventDefault(), this._commit()) : t.key === "Escape" && this._onCancel();
1912
+ }, this._onBlur = () => {
1913
+ this._commit();
1914
+ }, this.min = e == null ? void 0 : e.min, this.max = e == null ? void 0 : e.max, this.step = e == null ? void 0 : e.step;
1915
+ }
1916
+ mount(e, t, s, n) {
1917
+ this._onCommit = s, this._onCancel = n, 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 = `
1918
+ width:100%;height:100%;border:none;outline:none;padding:0 8px;
1919
+ font-size:var(--og-font-size,13px);text-align:right;
1920
+ background:var(--og-row-bg,#fff);box-sizing:border-box;
1921
+ `, this.input.addEventListener("keydown", this._onKeyDown), this.input.addEventListener("blur", this._onBlur), e.appendChild(this.input);
1922
+ }
1923
+ _commit() {
1924
+ const e = this.input.value === "" ? null : Number(this.input.value);
1925
+ this._onCommit(e);
1926
+ }
1927
+ getValue() {
1928
+ var e, t;
1929
+ return ((e = this.input) == null ? void 0 : e.value) === "" ? null : Number((t = this.input) == null ? void 0 : t.value);
1930
+ }
1931
+ focus() {
1932
+ var e, t;
1933
+ (e = this.input) == null || e.focus(), (t = this.input) == null || t.select();
1934
+ }
1935
+ destroy() {
1936
+ var e, t;
1937
+ (e = this.input) == null || e.removeEventListener("keydown", this._onKeyDown), (t = this.input) == null || t.removeEventListener("blur", this._onBlur);
1938
+ }
1939
+ }
1940
+ class ye {
1941
+ mount(e, t, s, n) {
1942
+ 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);
1943
+ }
1944
+ getValue() {
1945
+ var e;
1946
+ return (e = this.chk) == null ? void 0 : e.checked;
1947
+ }
1948
+ focus() {
1949
+ var e;
1950
+ (e = this.chk) == null || e.focus();
1951
+ }
1952
+ destroy() {
1953
+ }
1954
+ }
1955
+ function Ae(d) {
1956
+ const e = d.editor;
1957
+ if (!e)
1958
+ switch (d.type) {
1959
+ case "number":
1960
+ return new we();
1961
+ case "date":
1962
+ return new pe();
1963
+ case "boolean":
1964
+ return new ye();
1965
+ case "select":
1966
+ return new fe(d.options ?? [], d.optionsFn);
1967
+ default:
1968
+ return new me();
1969
+ }
1970
+ if (typeof e == "string")
1971
+ switch (e) {
1972
+ case "number":
1973
+ return new we();
1974
+ case "date":
1975
+ return new pe();
1976
+ case "select":
1977
+ return new fe(d.options ?? [], d.optionsFn);
1978
+ case "checkbox":
1979
+ return new ye();
1980
+ default:
1981
+ return new me();
1982
+ }
1983
+ switch (e.type) {
1984
+ case "number": {
1985
+ const t = {};
1986
+ 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);
1987
+ }
1988
+ case "date":
1989
+ return new pe();
1990
+ case "select":
1991
+ return new fe(e.options ?? [], d.optionsFn);
1992
+ case "checkbox":
1993
+ return new ye();
1994
+ default:
1995
+ return new me();
1996
+ }
1997
+ }
1998
+ function Z(d) {
1999
+ const e = typeof d.renderer == "string" ? d.renderer : d.renderer && typeof d.renderer == "object" ? d.renderer.type : "";
2000
+ return d.type === "boolean" || d.type === "checkbox" || e === "checkbox" || e === "switch";
2001
+ }
2002
+ class Et {
2003
+ constructor(e) {
2004
+ this._activeEditor = null, this._editCell = null, this._focusCell = null, this._dragColIdx = null, this._d = e;
2005
+ }
2006
+ // ─── 상태 접근자 ─────────────────────────────────────────
2007
+ get activeEditor() {
2008
+ return this._activeEditor;
2009
+ }
2010
+ get editCell() {
2011
+ return this._editCell;
2012
+ }
2013
+ get focusCell() {
2014
+ return this._focusCell;
2015
+ }
2016
+ get dragColIdx() {
2017
+ return this._dragColIdx;
2018
+ }
2019
+ set dragColIdx(e) {
2020
+ this._dragColIdx = e;
2021
+ }
2022
+ // ─── 포커스 셀 ───────────────────────────────────────────
2023
+ setFocusCell(e, t) {
2024
+ this._focusCell = { ri: e, ci: t }, this._d.scrollToRow(e), this._d.doRender();
2025
+ const s = this._d.getVisibleLeaves()[t], n = this._d.data.getRowByIndex(e);
2026
+ if (s && n) {
2027
+ const i = n[s.field];
2028
+ this._d.announce(
2029
+ `${e + 1}행 ${t + 1}열, ${s.header}: ${i == null ? "빈 값" : String(i)}`
2030
+ );
2031
+ }
2032
+ }
2033
+ clearFocusCell() {
2034
+ this._focusCell = null;
2035
+ }
2036
+ // ─── 편집 시작 (키보드) ──────────────────────────────────
2037
+ startEditByKey(e, t) {
2038
+ var a, c, h;
2039
+ const s = this._d.getVisibleLeaves()[t];
2040
+ if (!s) return;
2041
+ if (Z(s)) {
2042
+ const u = this._d.getOptions();
2043
+ if (s.editable !== !1 && (s.editable !== void 0 || u.editable)) {
2044
+ const E = this._d.data.getRowByIndex(e);
2045
+ E && this._d.writeCell(e, s.field, !E[s.field]);
2046
+ }
2047
+ return;
2048
+ }
2049
+ const n = this._d.data.getRowByIndex(e);
2050
+ if (s.editable === !1 || typeof s.editable == "function" && !s.editable(n, e)) return;
2051
+ this.commitEdit();
2052
+ const i = (a = this._d.getRenderer()) == null ? void 0 : a.getCellEl(e, t);
2053
+ if (!i) return;
2054
+ i.innerHTML = "";
2055
+ const o = Ae(s);
2056
+ this._activeEditor = o, this._editCell = { ri: e, ci: t };
2057
+ const l = {
2058
+ type: "editStart",
2059
+ rowIndex: e,
2060
+ columnIndex: t,
2061
+ field: s.field,
2062
+ oldValue: n == null ? void 0 : n[s.field],
2063
+ newValue: n == null ? void 0 : n[s.field],
2064
+ row: n,
2065
+ column: s
2066
+ };
2067
+ this._d.emit("editStart", l), (h = (c = this._d.getOptions()).onEditStart) == null || h.call(c, l), i.classList.add("og-editing");
2068
+ const r = {
2069
+ value: n == null ? void 0 : n[s.field],
2070
+ row: n,
2071
+ rowIndex: e,
2072
+ column: s,
2073
+ colIndex: t,
2074
+ isSelected: !0,
2075
+ rowState: "none"
2076
+ };
2077
+ o.mount(
2078
+ i,
2079
+ r,
2080
+ (u) => this.commitEditWithValue(e, t, u),
2081
+ () => this.cancelEdit()
2082
+ ), requestAnimationFrame(() => o.focus());
2083
+ }
2084
+ // ─── 편집 시작 (마우스) ──────────────────────────────────
2085
+ startEdit(e, t, s) {
2086
+ var h, u;
2087
+ const n = this._d.getOptions();
2088
+ if (!n.editable) return;
2089
+ const i = this._d.getVisibleLeaves()[t];
2090
+ if (!i || Z(i)) return;
2091
+ const o = this._d.data.getRowByIndex(e);
2092
+ if (i.editable === !1 || typeof i.editable == "function" && !i.editable(o, e) || !i.editable && !n.editable) return;
2093
+ this.commitEdit();
2094
+ const l = (h = this._d.getRenderer()) == null ? void 0 : h.getCellEl(e, t);
2095
+ if (!l) return;
2096
+ l.innerHTML = "";
2097
+ const r = Ae(i);
2098
+ this._activeEditor = r, this._editCell = { ri: e, ci: t };
2099
+ const a = {
2100
+ type: "editStart",
2101
+ rowIndex: e,
2102
+ columnIndex: t,
2103
+ field: i.field,
2104
+ oldValue: o == null ? void 0 : o[i.field],
2105
+ newValue: o == null ? void 0 : o[i.field],
2106
+ row: o,
2107
+ column: i
2108
+ };
2109
+ this._d.emit("editStart", a), (u = n.onEditStart) == null || u.call(n, a), l.classList.add("og-editing");
2110
+ const c = {
2111
+ value: o == null ? void 0 : o[i.field],
2112
+ row: o,
2113
+ rowIndex: e,
2114
+ column: i,
2115
+ colIndex: t,
2116
+ isSelected: !0,
2117
+ rowState: "none"
2118
+ };
2119
+ r.mount(
2120
+ l,
2121
+ c,
2122
+ (g) => this.commitEditWithValue(e, t, g),
2123
+ () => this.cancelEdit()
2124
+ ), requestAnimationFrame(() => r.focus());
2125
+ }
2126
+ // ─── 편집 종료 ───────────────────────────────────────────
2127
+ commitEdit() {
2128
+ if (!this._activeEditor || !this._editCell) return;
2129
+ const e = this._activeEditor.getValue(), { ri: t, ci: s } = this._editCell;
2130
+ this._finishEdit(t, s, e, !1);
2131
+ }
2132
+ commitEditWithValue(e, t, s) {
2133
+ this._finishEdit(e, t, s, !1);
2134
+ }
2135
+ cancelEdit() {
2136
+ if (!this._editCell) return;
2137
+ const { ri: e, ci: t } = this._editCell;
2138
+ this._finishEdit(e, t, void 0, !0);
2139
+ }
2140
+ _finishEdit(e, t, s, n) {
2141
+ var l, r, a;
2142
+ if (!this._activeEditor) return;
2143
+ const i = this._d.getVisibleLeaves()[t], o = (l = this._d.getRenderer()) == null ? void 0 : l.getCellEl(e, t);
2144
+ if (o && (this._activeEditor.destroy(), o.classList.remove("og-editing")), this._activeEditor = null, this._editCell = null, !n && i) {
2145
+ const c = this._d.data.getCellValue(e, i.field);
2146
+ if (s !== c) {
2147
+ this._d.data.updateCell(e, i.field, s);
2148
+ const h = this._d.data.getRowByIndex(e), u = this._d.getOptions(), g = {
2149
+ type: "editEnd",
2150
+ rowIndex: e,
2151
+ columnIndex: t,
2152
+ field: i.field,
2153
+ oldValue: c,
2154
+ newValue: s,
2155
+ row: h,
2156
+ column: i
2157
+ };
2158
+ 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());
2159
+ }
2160
+ }
2161
+ this._d.doRender(), requestAnimationFrame(() => this._d.getContainer().focus({ preventScroll: !0 }));
2162
+ }
2163
+ }
2164
+ class St {
2165
+ constructor(e, t, s, n, i) {
2166
+ this._selects = /* @__PURE__ */ new Map(), this._selected = {}, this._config = t, this._onFilter = s, this._onReset = n, this._el = document.createElement("fieldset"), this._el.className = "og-filter-select";
2167
+ const o = document.createElement("legend");
2168
+ o.className = "og-filter-select-legend", o.textContent = t.legend ?? "필터", this._el.appendChild(o);
2169
+ const l = document.createElement("div");
2170
+ l.className = "og-filter-select-row";
2171
+ for (const a of t.columns) {
2172
+ const c = `og-fsel-${a.field}`, h = document.createElement("div");
2173
+ h.className = "og-filter-select-group";
2174
+ const u = document.createElement("label");
2175
+ u.htmlFor = c, u.textContent = a.label, u.className = "og-filter-select-label";
2176
+ const g = document.createElement("select");
2177
+ g.id = c, g.className = "og-filter-select-sel", g.setAttribute("aria-label", a.label), i && g.setAttribute("aria-controls", i), 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);
2178
+ }
2179
+ const r = document.createElement("button");
2180
+ 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);
2181
+ }
2182
+ // ─── 옵션 해결 ────────────────────────────────────────
2183
+ /**
2184
+ * 컬럼의 옵션 목록을 계산한다.
2185
+ *
2186
+ * @param col 대상 컬럼 정의
2187
+ * @param parentValue 부모 선택값 (캐스케이딩 필터에 사용)
2188
+ */
2189
+ _resolve(e, t) {
2190
+ if (e.options) return e.options;
2191
+ let s = e.data ?? [];
2192
+ e.dependsOn && e.dependsOnKey && t && (s = s.filter(
2193
+ (o) => String(o[e.dependsOnKey] ?? "") === t
2194
+ ));
2195
+ const n = e.valueKey ?? "value", i = e.textKey ?? n;
2196
+ return s.map((o) => ({
2197
+ value: String(o[n] ?? ""),
2198
+ text: String(o[i] ?? o[n] ?? "")
2199
+ }));
2200
+ }
2201
+ // ─── select DOM 채우기 ────────────────────────────────
2202
+ _fill(e, t, s) {
2203
+ e.innerHTML = "";
2204
+ const n = document.createElement("option");
2205
+ n.value = "", n.textContent = "전체", e.appendChild(n);
2206
+ for (const i of t) {
2207
+ const o = document.createElement("option");
2208
+ o.value = i.value, o.textContent = i.text, e.appendChild(o);
2209
+ }
2210
+ e.disabled = !s;
2211
+ }
2212
+ // ─── 선택 변경 처리 ───────────────────────────────────
2213
+ _onChange(e, t) {
2214
+ const s = this._config.columns.find((i) => i.field === e), n = s.filterKey ?? s.field;
2215
+ t ? (this._selected[e] = t, this._onFilter(n, [{ operator: "=", value: t }])) : (delete this._selected[e], this._onReset(n)), this._cascade(e);
2216
+ }
2217
+ /**
2218
+ * 부모 컬럼 변경 후 자식 컬럼 옵션을 재계산한다 (재귀).
2219
+ */
2220
+ _cascade(e) {
2221
+ const t = this._selected[e] ?? "";
2222
+ for (const s of this._config.columns) {
2223
+ if (s.dependsOn !== e) continue;
2224
+ const n = this._selects.get(s.field);
2225
+ if (!n) continue;
2226
+ const i = s.filterKey ?? s.field;
2227
+ t ? (this._fill(n, this._resolve(s, t), !0), n.value = "", delete this._selected[s.field], this._onReset(i)) : (this._fill(n, [], !1), delete this._selected[s.field], this._onReset(i), this._cascade(s.field));
2228
+ }
2229
+ }
2230
+ // ─── 전체 초기화 ──────────────────────────────────────
2231
+ _reset() {
2232
+ this._selected = {};
2233
+ for (const e of this._config.columns) {
2234
+ const t = this._selects.get(e.field), s = e.filterKey ?? e.field;
2235
+ t && (e.dependsOn ? this._fill(t, [], !1) : (t.value = "", t.disabled = !1), this._onReset(s));
2236
+ }
2237
+ }
2238
+ // ─── 공개 API ─────────────────────────────────────────
2239
+ reset() {
2240
+ this._reset();
2241
+ }
2242
+ destroy() {
2243
+ this._el.remove();
2244
+ }
2245
+ }
2246
+ class Lt {
2247
+ constructor(e, t, s) {
2248
+ 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 = `
2249
+ display:flex;align-items:center;justify-content:center;gap:4px;
2250
+ padding:6px 8px;border-top:1px solid var(--og-border-color,#e0e0e0);
2251
+ background:var(--og-header-bg,#f5f5f5);flex-shrink:0;user-select:none;
2252
+ font-size:12px;color:var(--og-text-color,#333);
2253
+ `, e.appendChild(this._el), this._render();
2254
+ }
2255
+ get page() {
2256
+ return this._page;
2257
+ }
2258
+ get pageSize() {
2259
+ return this._pageSize;
2260
+ }
2261
+ get totalPages() {
2262
+ return Math.max(1, Math.ceil(this._totalRows / this._pageSize));
2263
+ }
2264
+ /** 전체 행 수 갱신 → 현재 페이지 유효성 검사 후 재렌더 */
2265
+ setTotalRows(e) {
2266
+ this._totalRows = e, this._page > this.totalPages && (this._page = this.totalPages), this._render();
2267
+ }
2268
+ setPageSize(e) {
2269
+ this._pageSize = e, this._page = 1, this._render(), this._emit();
2270
+ }
2271
+ goTo(e) {
2272
+ const t = Math.max(1, Math.min(e, this.totalPages));
2273
+ t !== this._page && (this._page = t, this._render(), this._emit());
2274
+ }
2275
+ /** 현재 페이지의 [startIndex, endIndex] 반환 (DataLayer 인덱스 기준) */
2276
+ getRange() {
2277
+ const e = (this._page - 1) * this._pageSize, t = Math.min(e + this._pageSize - 1, this._totalRows - 1);
2278
+ return { start: e, end: t };
2279
+ }
2280
+ _emit() {
2281
+ this._onChange({
2282
+ page: this._page,
2283
+ pageSize: this._pageSize,
2284
+ totalRows: this._totalRows,
2285
+ totalPages: this.totalPages
2286
+ });
2287
+ }
2288
+ _render() {
2289
+ this._el.innerHTML = "";
2290
+ const e = this.totalPages, t = document.createElement("span");
2291
+ t.style.cssText = "display:flex;align-items:center;gap:3px;margin-right:8px;";
2292
+ const s = document.createElement("span");
2293
+ s.textContent = "행/페이지:", s.style.color = "#888";
2294
+ const n = document.createElement("select");
2295
+ n.style.cssText = "padding:2px 4px;border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;font-size:11px;cursor:pointer;";
2296
+ for (const c of [10, 20, 50, 100, 200]) {
2297
+ const h = document.createElement("option");
2298
+ h.value = String(c), h.textContent = String(c), c === this._pageSize && (h.selected = !0), n.appendChild(h);
2299
+ }
2300
+ n.addEventListener("change", () => this.setPageSize(Number(n.value))), t.appendChild(s), t.appendChild(n), this._el.appendChild(t);
2301
+ const i = document.createElement("span"), { start: o, end: l } = this.getRange();
2302
+ i.textContent = this._totalRows > 0 ? `${o + 1}–${l + 1} / ${this._totalRows}건` : "0건", i.style.cssText = "margin-right:8px;color:#888;", this._el.appendChild(i);
2303
+ const r = (c, h, u) => {
2304
+ const g = document.createElement("button");
2305
+ return g.textContent = c, g.disabled = u, g.style.cssText = `
2306
+ min-width:28px;height:24px;padding:0 6px;
2307
+ border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;
2308
+ background:${u ? "#f5f5f5" : "#fff"};
2309
+ color:${u ? "#bbb" : "var(--og-text-color,#333)"};
2310
+ cursor:${u ? "default" : "pointer"};font-size:12px;
2311
+ `, u || g.addEventListener("click", () => this.goTo(h)), g;
2312
+ };
2313
+ this._el.appendChild(r("«", 1, this._page === 1)), this._el.appendChild(r("‹", this._page - 1, this._page === 1));
2314
+ const a = Ft(this._page, e);
2315
+ for (const c of a)
2316
+ if (c === -1) {
2317
+ const h = document.createElement("span");
2318
+ h.textContent = "…", h.style.padding = "0 3px", this._el.appendChild(h);
2319
+ } else {
2320
+ const h = r(String(c), c, c === this._page);
2321
+ 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);
2322
+ }
2323
+ this._el.appendChild(r("›", this._page + 1, this._page === e)), this._el.appendChild(r("»", e, this._page === e));
2324
+ }
2325
+ destroy() {
2326
+ this._el.remove();
2327
+ }
2328
+ }
2329
+ function Ft(d, e) {
2330
+ if (e <= 7) return Array.from({ length: e }, (s, n) => n + 1);
2331
+ const t = [1];
2332
+ d > 3 && t.push(-1);
2333
+ for (let s = Math.max(2, d - 1); s <= Math.min(e - 1, d + 1); s++)
2334
+ t.push(s);
2335
+ return d < e - 2 && t.push(-1), t.push(e), t;
2336
+ }
2337
+ class Tt {
2338
+ constructor(e, t, s) {
2339
+ this._drag = null, this._bodyEl = e, this._rowHeight = t, this._onDrop = s, this._onMouseMove = this._onMouseMove.bind(this), this._onMouseUp = this._onMouseUp.bind(this);
2340
+ }
2341
+ /** 행 엘리먼트에 드래그 핸들 삽입 */
2342
+ attachHandle(e, t, s) {
2343
+ const n = document.createElement("div");
2344
+ return n.className = "og-drag-handle", n.innerHTML = "⠿", n.style.cssText = `
2345
+ width:18px;min-width:18px;height:100%;
2346
+ display:flex;align-items:center;justify-content:center;
2347
+ cursor:grab;font-size:14px;color:#bbb;flex-shrink:0;
2348
+ user-select:none;border-right:1px solid var(--og-border-color,#e0e0e0);
2349
+ `, n.addEventListener("mousedown", (i) => {
2350
+ i.preventDefault(), i.stopPropagation(), this._startDrag(i, e, t, s);
2351
+ }), n;
2352
+ }
2353
+ _startDrag(e, t, s, n) {
2354
+ const i = t.getBoundingClientRect(), o = document.createElement("div");
2355
+ o.style.cssText = `
2356
+ position:fixed;left:${i.left}px;top:${i.top}px;
2357
+ width:${i.width}px;height:${i.height}px;
2358
+ background:rgba(25,118,210,0.12);border:2px dashed #1976d2;
2359
+ box-sizing:border-box;pointer-events:none;z-index:9999;
2360
+ border-radius:2px;opacity:0.9;
2361
+ `, document.body.appendChild(o);
2362
+ const l = document.createElement("div");
2363
+ l.style.cssText = `
2364
+ position:absolute;left:0;right:0;height:2px;
2365
+ background:#1976d2;pointer-events:none;z-index:9998;display:none;
2366
+ `, this._bodyEl.appendChild(l), this._drag = {
2367
+ fromIndex: s,
2368
+ startY: e.clientY,
2369
+ ghostEl: o,
2370
+ indicator: l,
2371
+ rowHeight: this._rowHeight,
2372
+ totalRows: n,
2373
+ bodyEl: this._bodyEl,
2374
+ currentTarget: s
2375
+ }, document.addEventListener("mousemove", this._onMouseMove), document.addEventListener("mouseup", this._onMouseUp);
2376
+ }
2377
+ _onMouseMove(e) {
2378
+ if (!this._drag) return;
2379
+ const t = this._drag, s = e.clientY - t.startY, n = t.ghostEl.getBoundingClientRect();
2380
+ t.ghostEl.style.top = `${n.top + s}px`, t.startY = e.clientY;
2381
+ const i = t.bodyEl.getBoundingClientRect(), o = e.clientY - i.top + t.bodyEl.scrollTop, l = Math.max(0, Math.min(t.totalRows - 1, Math.round(o / t.rowHeight)));
2382
+ t.currentTarget = l;
2383
+ const r = l * t.rowHeight;
2384
+ t.indicator.style.display = "block", t.indicator.style.top = `${r}px`;
2385
+ }
2386
+ _onMouseUp(e) {
2387
+ if (document.removeEventListener("mousemove", this._onMouseMove), document.removeEventListener("mouseup", this._onMouseUp), !this._drag) return;
2388
+ const { fromIndex: t, currentTarget: s, ghostEl: n, indicator: i } = this._drag;
2389
+ this._drag = null, n.remove(), i.remove(), t !== s && this._onDrop(t, s);
2390
+ }
2391
+ destroy() {
2392
+ var e, t;
2393
+ 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;
2394
+ }
2395
+ }
2396
+ class Q {
2397
+ constructor() {
2398
+ this._map = /* @__PURE__ */ new Map();
2399
+ }
2400
+ static _key(e, t) {
2401
+ return `${e}:${t}`;
2402
+ }
2403
+ /** 수동 병합 정의 목록으로 맵 구성 */
2404
+ applyMergeCells(e) {
2405
+ this._map.clear();
2406
+ for (const t of e) {
2407
+ const s = Math.max(1, t.rowSpan ?? 1), n = Math.max(1, t.colSpan ?? 1);
2408
+ this._map.set(Q._key(t.row, t.col), {
2409
+ rowSpan: s,
2410
+ colSpan: n,
2411
+ hidden: !1
2412
+ });
2413
+ for (let i = 0; i < s; i++)
2414
+ for (let o = 0; o < n; o++)
2415
+ i === 0 && o === 0 || this._map.set(Q._key(t.row + i, t.col + o), {
2416
+ rowSpan: 1,
2417
+ colSpan: 1,
2418
+ hidden: !0
2419
+ });
2420
+ }
2421
+ }
2422
+ /**
2423
+ * 자동 병합: 지정 컬럼 인덱스 목록에 대해 연속 같은 값을 rowSpan으로 병합.
2424
+ * data: 현재 표시 순서의 행 배열, colIndexes: 자동병합할 leaf 컬럼 인덱스
2425
+ * fields: colIndexes[i] 에 대응하는 field 이름
2426
+ */
2427
+ applyAutoMerge(e, t, s) {
2428
+ var n, i;
2429
+ this._map.clear();
2430
+ for (let o = 0; o < t.length; o++) {
2431
+ const l = t[o], r = s[o];
2432
+ let a = 0;
2433
+ for (let c = 1; c <= e.length; c++) {
2434
+ const h = (n = e[c - 1]) == null ? void 0 : n[r], u = c < e.length ? (i = e[c]) == null ? void 0 : i[r] : void 0;
2435
+ if (c === e.length || u !== h) {
2436
+ const g = c - a;
2437
+ if (g > 1) {
2438
+ this._map.set(Q._key(a, l), {
2439
+ rowSpan: g,
2440
+ colSpan: 1,
2441
+ hidden: !1
2442
+ });
2443
+ for (let E = a + 1; E < c; E++)
2444
+ this._map.set(Q._key(E, l), {
2445
+ rowSpan: 1,
2446
+ colSpan: 1,
2447
+ hidden: !0
2448
+ });
2449
+ }
2450
+ a = c;
2451
+ }
2452
+ }
2453
+ }
2454
+ }
2455
+ /** 셀 병합 정보 조회. 없으면 null */
2456
+ getInfo(e, t) {
2457
+ return this._map.get(Q._key(e, t)) ?? null;
2458
+ }
2459
+ /** 병합 맵 초기화 */
2460
+ clear() {
2461
+ this._map.clear();
2462
+ }
2463
+ get isEmpty() {
2464
+ return this._map.size === 0;
2465
+ }
2466
+ }
2467
+ const Dt = [
2468
+ { id: "sort-asc", label: "오름차순 정렬", icon: "↑", action: "sortAsc" },
2469
+ { id: "sort-desc", label: "내림차순 정렬", icon: "↓", action: "sortDesc" },
2470
+ { type: "divider" },
2471
+ { id: "find", label: "찾기", icon: "🔍", action: "find" },
2472
+ { type: "divider" },
2473
+ { id: "excel", label: "Excel로 저장", icon: "📊", action: "excel" },
2474
+ { id: "csv", label: "CSV로 저장", icon: "📄", action: "csv" },
2475
+ { id: "print", label: "인쇄", icon: "🖨", action: "print" }
2476
+ ];
2477
+ class $t {
2478
+ /**
2479
+ * @param _anchor 그리드 컨테이너 엘리먼트 — CSS 변수 상속 기준점
2480
+ * @param _actions 기본 액션 핸들러 (OpenGrid에서 주입)
2481
+ */
2482
+ constructor(e, t) {
2483
+ this._anchor = e, this._actions = t, this._el = null, this._docClick = null, this._docKey = null, this._docScroll = null, this._docMouseMove = null, this._focusIdx = -1;
2484
+ }
2485
+ open(e, t) {
2486
+ this.close();
2487
+ const s = t ?? Dt, n = document.createElement("div");
2488
+ n.className = "og-context-menu", n.setAttribute("role", "menu");
2489
+ for (const i of s) {
2490
+ if (i.type === "divider") {
2491
+ const r = document.createElement("div");
2492
+ r.className = "og-cm-divider", r.setAttribute("role", "separator"), n.appendChild(r);
2493
+ continue;
2494
+ }
2495
+ const o = document.createElement("button");
2496
+ if (o.className = "og-cm-item", o.setAttribute("role", "menuitem"), o.setAttribute("tabindex", "-1"), i.disabled && (o.classList.add("og-cm-disabled"), o.setAttribute("aria-disabled", "true")), i.icon) {
2497
+ const r = document.createElement("span");
2498
+ if (r.className = "og-cm-icon", /^[a-zA-Z][\w-]*(\s+[\w-]+)+$/.test(i.icon.trim())) {
2499
+ const a = document.createElement("i");
2500
+ a.className = i.icon, r.appendChild(a);
2501
+ } else
2502
+ r.textContent = i.icon;
2503
+ r.setAttribute("aria-hidden", "true"), o.appendChild(r);
2504
+ }
2505
+ const l = document.createElement("span");
2506
+ l.className = "og-cm-label", l.textContent = i.label ?? "", o.appendChild(l), o.addEventListener("click", (r) => {
2507
+ r.stopPropagation(), i.disabled || this._runAction(i), this.close();
2508
+ }), n.appendChild(o);
2509
+ }
2510
+ this._anchor.appendChild(n), this._el = n, this._docMouseMove = (i) => {
2511
+ if (!this._el) return;
2512
+ const o = this._el.getBoundingClientRect();
2513
+ (i.clientX < o.left - 4 || i.clientX > o.right + 4 || i.clientY < o.top - 4 || i.clientY > o.bottom + 4) && this.close();
2514
+ }, this._position(n, e.clientX, e.clientY, () => {
2515
+ this._el === n && document.addEventListener("mousemove", this._docMouseMove, { capture: !0, passive: !0 });
2516
+ }), this._docClick = (i) => {
2517
+ n.contains(i.target) || this.close();
2518
+ }, this._docKey = (i) => {
2519
+ if (i.key === "Escape") {
2520
+ this.close();
2521
+ return;
2522
+ }
2523
+ if (i.key === "ArrowDown") {
2524
+ i.preventDefault(), this._moveFocus(1);
2525
+ return;
2526
+ }
2527
+ if (i.key === "ArrowUp") {
2528
+ i.preventDefault(), this._moveFocus(-1);
2529
+ return;
2530
+ }
2531
+ if (i.key === "Enter") {
2532
+ const o = n.querySelector(".og-cm-item:focus");
2533
+ o == null || o.click();
2534
+ }
2535
+ }, this._docScroll = () => this.close(), setTimeout(() => {
2536
+ document.addEventListener("click", this._docClick), document.addEventListener("keydown", this._docKey), window.addEventListener("scroll", this._docScroll, { passive: !0 });
2537
+ }, 0), this._focusIdx = -1, this._moveFocus(1);
2538
+ }
2539
+ close() {
2540
+ var e;
2541
+ (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;
2542
+ }
2543
+ destroy() {
2544
+ this.close();
2545
+ }
2546
+ // ── 위치 결정 ─────────────────────────────────────────────
2547
+ _position(e, t, s, n) {
2548
+ e.style.cssText = "position:fixed;visibility:hidden;left:0;top:0;", requestAnimationFrame(() => {
2549
+ const { width: i, height: o } = e.getBoundingClientRect(), l = window.innerWidth, r = window.innerHeight, a = t + i > l ? Math.max(0, t - i) : t, c = s + o > r ? Math.max(0, s - o) : s;
2550
+ e.style.cssText = `position:fixed;left:${a}px;top:${c}px;z-index:9999;`, n == null || n();
2551
+ });
2552
+ }
2553
+ // ── 키보드 포커스 이동 ────────────────────────────────────
2554
+ _moveFocus(e) {
2555
+ var s;
2556
+ if (!this._el) return;
2557
+ const t = Array.from(
2558
+ this._el.querySelectorAll(".og-cm-item:not(.og-cm-disabled)")
2559
+ );
2560
+ t.length && (this._focusIdx = (this._focusIdx + e + t.length) % t.length, (s = t[this._focusIdx]) == null || s.focus());
2561
+ }
2562
+ // ── 액션 실행 ─────────────────────────────────────────────
2563
+ _runAction(e) {
2564
+ if (typeof e.action == "function") {
2565
+ e.action();
2566
+ return;
2567
+ }
2568
+ switch (e.action) {
2569
+ case "sortAsc":
2570
+ this._actions.onSortAsc();
2571
+ break;
2572
+ case "sortDesc":
2573
+ this._actions.onSortDesc();
2574
+ break;
2575
+ case "find":
2576
+ this._actions.onFind();
2577
+ break;
2578
+ case "excel":
2579
+ this._actions.onExcel();
2580
+ break;
2581
+ case "csv":
2582
+ this._actions.onCsv();
2583
+ break;
2584
+ case "print":
2585
+ this._actions.onPrint();
2586
+ break;
2587
+ }
2588
+ }
2589
+ }
2590
+ class ze {
2591
+ constructor(e, t) {
2592
+ this._sheets = /* @__PURE__ */ new Map(), this._active = "", this._onSwitch = t, this._tabBar = this._buildTabBar(e);
2593
+ }
2594
+ // ── 시트 CRUD ────────────────────────────────────────────
2595
+ add(e, t = [], s = []) {
2596
+ if (this._sheets.has(e))
2597
+ throw new Error(`WorksheetManager: 시트 '${e}'이 이미 존재합니다`);
2598
+ this._sheets.set(e, { name: e, columns: t, data: s }), this._renderTabs(), this._sheets.size === 1 && this.switch(e);
2599
+ }
2600
+ remove(e) {
2601
+ if (!this._sheets.has(e)) return;
2602
+ if (this._sheets.size === 1)
2603
+ throw new Error("WorksheetManager: 마지막 시트는 삭제할 수 없습니다");
2604
+ const t = this._active === e;
2605
+ this._sheets.delete(e), this._renderTabs(), t && this.switch(this._sheets.keys().next().value);
2606
+ }
2607
+ rename(e, t) {
2608
+ if (!this._sheets.has(e)) return;
2609
+ if (this._sheets.has(t))
2610
+ throw new Error(`WorksheetManager: 시트 '${t}'이 이미 존재합니다`);
2611
+ this._sheets.get(e);
2612
+ const s = Array.from(this._sheets.entries()).map(
2613
+ ([n, i]) => n === e ? [t, { ...i, name: t }] : [n, i]
2614
+ );
2615
+ this._sheets = new Map(s), this._active === e && (this._active = t), this._renderTabs();
2616
+ }
2617
+ switch(e) {
2618
+ const t = this._sheets.get(e);
2619
+ if (!t) throw new Error(`WorksheetManager: 시트 '${e}'을 찾을 수 없습니다`);
2620
+ this._active = e, this._renderTabs(), this._onSwitch(e, t);
2621
+ }
2622
+ get(e) {
2623
+ return this._sheets.get(e);
2624
+ }
2625
+ getNames() {
2626
+ return Array.from(this._sheets.keys());
2627
+ }
2628
+ getActive() {
2629
+ return this._active;
2630
+ }
2631
+ /** 현재 활성 시트의 data를 갱신 (그리드 편집 동기화용) */
2632
+ syncData(e, t) {
2633
+ const s = this._sheets.get(e);
2634
+ s && (s.data = t);
2635
+ }
2636
+ destroy() {
2637
+ this._tabBar.remove();
2638
+ }
2639
+ // ── 탭 UI ────────────────────────────────────────────────
2640
+ _buildTabBar(e) {
2641
+ const t = document.createElement("div");
2642
+ return t.className = "og-sheet-tabs", e.appendChild(t), t;
2643
+ }
2644
+ _renderTabs() {
2645
+ this._tabBar.innerHTML = "";
2646
+ for (const t of this._sheets.keys()) {
2647
+ const s = document.createElement("button");
2648
+ 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", () => {
2649
+ t !== this._active && this.switch(t);
2650
+ }), s.addEventListener("dblclick", () => this._startRename(s, t)), this._tabBar.appendChild(s);
2651
+ }
2652
+ const e = document.createElement("button");
2653
+ e.className = "og-sheet-add", e.textContent = "+", e.setAttribute("aria-label", "새 워크시트 추가"), e.addEventListener("click", () => {
2654
+ const t = `Sheet${this._sheets.size + 1}`;
2655
+ this.add(t, [], []), this.switch(t);
2656
+ }), this._tabBar.appendChild(e);
2657
+ }
2658
+ /** 탭 더블클릭 → input으로 전환해 이름 변경 */
2659
+ _startRename(e, t) {
2660
+ const s = document.createElement("input");
2661
+ s.className = "og-sheet-tab-rename", s.value = t, e.replaceWith(s), s.focus(), s.select();
2662
+ const n = () => {
2663
+ const i = s.value.trim() || t;
2664
+ try {
2665
+ i !== t ? this.rename(t, i) : this._renderTabs();
2666
+ } catch {
2667
+ this._renderTabs();
2668
+ }
2669
+ };
2670
+ s.addEventListener("blur", n), s.addEventListener("keydown", (i) => {
2671
+ i.key === "Enter" && s.blur(), i.key === "Escape" && (s.value = t, s.blur());
2672
+ });
2673
+ }
2674
+ }
2675
+ class At {
2676
+ constructor(e) {
2677
+ this._d = e;
2678
+ }
2679
+ _readCssVar(e) {
2680
+ return getComputedStyle(this._d.getContainer()).getPropertyValue(e).trim();
2681
+ }
2682
+ _hexToXlsxRgb(e) {
2683
+ const t = e.trim(), s = t.match(/^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)/i);
2684
+ if (s)
2685
+ return [s[1], s[2], s[3]].map((i) => parseInt(i).toString(16).padStart(2, "0")).join("").toUpperCase();
2686
+ const n = t.replace("#", "").toUpperCase();
2687
+ return n.length === 3 ? n[0] + n[0] + n[1] + n[1] + n[2] + n[2] : n.length === 6 ? n : "";
2688
+ }
2689
+ exportExcel(e) {
2690
+ const t = typeof e == "string" ? { filename: e } : e ?? {};
2691
+ let s = t.filename ?? "export";
2692
+ s.toLowerCase().endsWith(".xlsx") || (s += ".xlsx");
2693
+ const n = t.sheetName ?? (this._d.getOptions().ariaLabel || "Sheet1"), i = this._d.getData(), o = this._d.getColLayout().visibleLeaves.filter((r) => {
2694
+ var a;
2695
+ return !((a = t.exceptFields) != null && a.includes(r.field));
2696
+ }), l = t.includeHeader !== !1;
2697
+ import("./xlsx.min-Wavxcamn.js").then((r) => r.x).then(({ utils: r, writeFile: a }) => {
2698
+ var m;
2699
+ const c = [];
2700
+ l && c.push(o.map((b) => b.header));
2701
+ for (const b of i)
2702
+ c.push(o.map((k) => {
2703
+ const K = b[k.field];
2704
+ if (t.maskOnExport && k.mask && this._d.getMaskEnabled(k.field))
2705
+ return be(K == null ? "" : String(K), k.mask);
2706
+ const T = K;
2707
+ return T == null || T === "" ? "" : k.type === "number" && typeof T == "number" ? T : typeof T == "boolean" ? T ? "✓" : "" : typeof T == "object" ? "" : String(T);
2708
+ }));
2709
+ const h = r.aoa_to_sheet(c), u = this._d.getColWidths(), g = this._d.getColLayout();
2710
+ h["!cols"] = o.map((b) => ({
2711
+ wpx: u[g.getColumnIndex(b.field)] ?? 100
2712
+ })), h["!rows"] = c.map((b, k) => ({ hpx: k === 0 && l ? 22 : 19 }));
2713
+ const E = t.styleMode ?? "theme";
2714
+ let w = "1565C0", C = "FFFFFF", M = "FFFFFF", p = "EEF2FF", v = "212121", _ = "BDBDBD", F = 10;
2715
+ if (E === "theme") {
2716
+ const b = (K) => this._hexToXlsxRgb(K);
2717
+ w = b(this._readCssVar("--og-header-bg")) || w, C = b(this._readCssVar("--og-header-color")) || C, M = b(this._readCssVar("--og-row-bg")) || M, p = b(this._readCssVar("--og-row-alt-bg")) || p, v = b(this._readCssVar("--og-row-color")) || v, _ = b(this._readCssVar("--og-border-color")) || _;
2718
+ const k = this._readCssVar("--og-font-size");
2719
+ k && (F = Math.max(8, Math.round(parseFloat(k) * 0.75)));
2720
+ }
2721
+ const A = E === "none", H = {
2722
+ hdrFont: A ? {} : { bold: !0, color: { rgb: C }, sz: F, name: "맑은 고딕" },
2723
+ dataFont: A ? {} : { sz: F, color: { rgb: v }, name: "맑은 고딕" },
2724
+ hdrFill: A ? {} : { patternType: "solid", fgColor: { rgb: w } },
2725
+ evenFill: A ? {} : { patternType: "solid", fgColor: { rgb: M } },
2726
+ oddFill: A ? {} : { patternType: "solid", fgColor: { rgb: p } },
2727
+ hdrBorder: A ? {} : {
2728
+ top: { style: "medium", color: { rgb: w } },
2729
+ bottom: { style: "medium", color: { rgb: w } },
2730
+ left: { style: "thin", color: { rgb: w } },
2731
+ right: { style: "thin", color: { rgb: w } }
2732
+ },
2733
+ dataBorder: A ? {} : {
2734
+ top: { style: "thin", color: { rgb: _ } },
2735
+ bottom: { style: "thin", color: { rgb: _ } },
2736
+ left: { style: "thin", color: { rgb: _ } },
2737
+ right: { style: "thin", color: { rgb: _ } }
2738
+ }
2739
+ };
2740
+ c.forEach((b, k) => {
2741
+ const K = l && k === 0, ne = (l ? k - 1 : k) % 2 === 0;
2742
+ b.forEach((oe, V) => {
2743
+ const J = r.encode_cell({ r: k, c: V });
2744
+ h[J] || (h[J] = { t: "s", v: "" });
2745
+ const f = o[V], L = f.type === "number" || f.align === "right", D = K ? "center" : L ? "right" : f.align ?? "left";
2746
+ h[J].s = {
2747
+ font: K ? H.hdrFont : H.dataFont,
2748
+ fill: K ? H.hdrFill : ne ? H.evenFill : H.oddFill,
2749
+ border: K ? H.hdrBorder : H.dataBorder,
2750
+ alignment: { horizontal: D, vertical: "center", wrapText: !1 }
2751
+ };
2752
+ });
2753
+ });
2754
+ const $ = r.book_new();
2755
+ r.book_append_sheet($, h, n), a($, s, { cellStyles: !0 }), (m = t.onAfter) == null || m.call(t, new Blob([]));
2756
+ }).catch(() => {
2757
+ console.error("Excel 내보내기 실패: xlsx 패키지를 확인하세요.");
2758
+ });
2759
+ }
2760
+ exportCsv(e) {
2761
+ const t = typeof e == "string" ? { filename: e } : e ?? {}, s = this._d.getData(), n = this._d.getColLayout().visibleLeaves, i = n.map((r) => `"${r.header}"`).join(","), o = s.map((r) => n.map((a) => {
2762
+ const c = r[a.field] ?? "";
2763
+ if (t.maskOnExport && a.mask && this._d.getMaskEnabled(a.field))
2764
+ return be(String(c), a.mask);
2765
+ const h = c;
2766
+ return typeof h == "string" && h.includes(",") ? `"${h}"` : h;
2767
+ }).join(",")), l = t.filename ?? "export.csv";
2768
+ De("\uFEFF" + [i, ...o].join(`
2769
+ `), l);
2770
+ }
2771
+ exportJson(e) {
2772
+ const t = typeof e == "string" ? e : (e == null ? void 0 : e.filename) ?? "export.json";
2773
+ De(JSON.stringify(this._d.getData(), null, 2), t, "application/json");
2774
+ }
2775
+ print(e) {
2776
+ const t = (e == null ? void 0 : e.title) ?? "OPEN_GRID", s = (e == null ? void 0 : e.footerText) ?? "", n = this._d.getData(), i = this._d.getColLayout().visibleLeaves.filter((h) => {
2777
+ var u;
2778
+ return !((u = e == null ? void 0 : e.excludeFields) != null && u.includes(h.field));
2779
+ }), o = i.map((h) => `<th>${h.header ?? h.field}</th>`).join(""), l = n.map(
2780
+ (h) => `<tr>${i.map((u) => `<td>${String(h[u.field] ?? "")}</td>`).join("")}</tr>`
2781
+ ).join(""), r = s ? `<div class="og-print-footer">${s}</div>` : "", a = `<!DOCTYPE html>
2782
+ <html lang="ko"><head>
2783
+ <meta charset="UTF-8"><title>${t}</title>
2784
+ <style>
2785
+ @page{margin:0;}
2786
+ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:12px;margin:0;padding:1cm;}
2787
+ h2{margin:0 0 10px;font-size:14px;color:#333;}
2788
+ p{margin:0 0 8px;font-size:11px;color:#999;}
2789
+ table{border-collapse:collapse;width:100%;}
2790
+ th,td{border:1px solid #ccc;padding:5px 8px;text-align:left;white-space:nowrap;}
2791
+ th{background:#f5f5f5;font-weight:600;color:#333;}
2792
+ tr:nth-child(even) td{background:#fafafa;}
2793
+ .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;}
2794
+ </style>
2795
+ </head><body>
2796
+ <h2>${t}</h2>
2797
+ <p>${n.length}행 × ${i.length}열 · ${(/* @__PURE__ */ new Date()).toLocaleString("ko-KR")}</p>
2798
+ <table>
2799
+ <thead><tr>${o}</tr></thead>
2800
+ <tbody>${l}</tbody>
2801
+ </table>
2802
+ ${r}
2803
+ <script>window.addEventListener('load',()=>{window.print();window.addEventListener('afterprint',()=>window.close());});<\/script>
2804
+ </body></html>`, c = window.open("", "_blank", "width=960,height=640");
2805
+ c && (c.document.write(a), c.document.close());
2806
+ }
2807
+ exportSheetsExcel(e) {
2808
+ const t = this._d.getWsManager();
2809
+ if (!t) {
2810
+ this.exportExcel(e ?? "workbook");
2811
+ return;
2812
+ }
2813
+ const s = e ?? "workbook.xlsx";
2814
+ import("./xlsx.min-Wavxcamn.js").then((n) => n.x).then(({ utils: n, writeFile: i }) => {
2815
+ const o = n.book_new(), l = this._d.getOptions();
2816
+ for (const r of t.getNames()) {
2817
+ const a = t.get(r), c = a.columns.length ? a.columns : l.columns, h = [c.map((g) => g.header)];
2818
+ for (const g of a.data)
2819
+ h.push(c.map((E) => {
2820
+ const w = g[E.field];
2821
+ return w == null ? "" : typeof w == "boolean" ? w ? "✓" : "" : E.type === "number" && typeof w == "number" ? w : String(w);
2822
+ }));
2823
+ const u = n.aoa_to_sheet(h);
2824
+ u["!cols"] = c.map(() => ({ wpx: 100 })), n.book_append_sheet(o, u, r);
2825
+ }
2826
+ i(o, s.endsWith(".xlsx") ? s : s + ".xlsx", { cellStyles: !0 });
2827
+ }).catch(() => console.error("exportSheetsExcel: xlsx 패키지를 확인하세요."));
2828
+ }
2829
+ }
2830
+ class zt {
2831
+ constructor(e) {
2832
+ this._d = e;
2833
+ }
2834
+ fmtNum(e, t) {
2835
+ if (!t)
2836
+ return Math.round(e).toLocaleString("ko-KR");
2837
+ const s = t.includes("#") || t.includes(","), n = t.match(/\.(\d+)$/), i = n ? parseInt(n[1], 10) : /^\d+$/.test(t) ? parseInt(t, 10) : 0, o = Math.abs(e).toFixed(i), [l = "0", r] = o.split("."), a = s ? l.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : l, c = r !== void 0 ? `${a}.${r}` : a;
2838
+ return e < 0 ? `-${c}` : c;
2839
+ }
2840
+ computeValues() {
2841
+ const e = this._d.getOptions().footer;
2842
+ if (!e || e.length === 0) return [];
2843
+ const t = this._d.getData();
2844
+ return e.filter((s) => s.field && s.op).map((s) => {
2845
+ const n = s.field, i = s.op, o = t.map((h) => h[n]).filter((h) => h != null && h !== "");
2846
+ let l = null;
2847
+ const r = i.toUpperCase();
2848
+ if (r === "SUM")
2849
+ l = o.length > 0 ? x.sum(o.map((h) => String(h))) : null;
2850
+ else if (r === "AVG")
2851
+ l = o.length > 0 ? x.sum(o.map((h) => String(h))).div(x.from(String(o.length))) : null;
2852
+ else if (r === "COUNT") {
2853
+ const h = o.length;
2854
+ return { _field: n, _value: h, _formatted: h.toLocaleString("ko-KR") };
2855
+ } 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);
2856
+ if (!l) return { _field: n, _value: null, _formatted: "" };
2857
+ const a = l.toNumber(), c = this.fmtNum(a, s.format);
2858
+ return { _field: n, _value: a, _formatted: c };
2859
+ });
2860
+ }
2861
+ render() {
2862
+ var h;
2863
+ const e = this._d.getContainer(), t = e.querySelector(".og-footer-bar");
2864
+ t == null || t.remove();
2865
+ const s = this._d.getOptions(), n = s.footer;
2866
+ if (!n || n.length === 0) return;
2867
+ const i = this._d.getColLayout().visibleLeaves, o = this._d.getColWidths() ?? i.map((u) => u.width ?? 100), l = new Map(
2868
+ this.computeValues().map((u) => [u._field, u])
2869
+ ), r = document.createElement("div");
2870
+ r.className = "og-footer-bar", r.style.cssText = [
2871
+ "display:flex;align-items:stretch;",
2872
+ `min-height:${s.footerHeight}px;`,
2873
+ "border-top:2px solid var(--og-primary,#1976d2);",
2874
+ "background:var(--og-header-bg,#f5f5f5);",
2875
+ "overflow:hidden;flex-shrink:0;font-size:13px;font-weight:600;"
2876
+ ].join("");
2877
+ let a = 0;
2878
+ if (s.stateColumn && (a += 24), s.draggable && (a += 18), s.rowNumber && (a += 44), s.checkColumn && (a += 36), a > 0) {
2879
+ const u = document.createElement("div");
2880
+ u.style.cssText = `width:${a}px;flex-shrink:0;border-right:1px solid var(--og-border-color,#e0e0e0);`, r.appendChild(u);
2881
+ }
2882
+ let c = 0;
2883
+ for (const u of n) {
2884
+ const g = Math.max(1, u.colspan ?? 1);
2885
+ let E = 0;
2886
+ for (let v = 0; v < g; v++)
2887
+ E += o[c + v] ?? 100;
2888
+ const w = i[c];
2889
+ c += g;
2890
+ const C = document.createElement("div");
2891
+ C.style.cssText = [
2892
+ `width:${E}px;min-width:${E}px;flex-shrink:0;`,
2893
+ "padding:4px 8px;box-sizing:border-box;overflow:hidden;",
2894
+ "border-right:1px solid var(--og-border-color,#e0e0e0);",
2895
+ "white-space:nowrap;text-overflow:ellipsis;"
2896
+ ].join("");
2897
+ const M = u.field, p = M ? l.get(M) : null;
2898
+ if (p) {
2899
+ const v = p._formatted ?? String(p._value ?? ""), _ = u.label ? `${u.label}: ` : "";
2900
+ C.textContent = _ + v, C.title = `${((h = u.op) == null ? void 0 : h.toUpperCase()) ?? ""} = ${v}`, C.style.color = "var(--og-primary,#1976d2)", C.style.textAlign = u.align ?? ((w == null ? void 0 : w.type) === "number", "right");
2901
+ } else u.label && (C.textContent = u.label, C.style.textAlign = u.align ?? "left", C.style.color = "var(--og-row-color,#212121)");
2902
+ r.appendChild(C);
2903
+ }
2904
+ s.footerPosition === "top" ? e.insertBefore(r, e.firstChild) : e.appendChild(r);
2905
+ }
2906
+ }
2907
+ class It {
2908
+ constructor(e) {
2909
+ this._d = e;
2910
+ }
2911
+ handleKeyDown(e) {
2912
+ const t = this._d.getEditMgr();
2913
+ if (t.activeEditor) return;
2914
+ this._d.handleCellKeyEvt("cellKeyDown", e);
2915
+ const s = this._d.getData(), n = this._d.getColLayout(), i = s.rowCount, o = n.visibleLeaves.length;
2916
+ if (i === 0 || o === 0) return;
2917
+ if ((e.ctrlKey || e.metaKey) && e.key === "c") {
2918
+ e.preventDefault(), this._copyToClipboard();
2919
+ return;
2920
+ }
2921
+ if ((e.ctrlKey || e.metaKey) && e.key === "v") {
2922
+ e.preventDefault(), this._pasteFromClipboard();
2923
+ return;
2924
+ }
2925
+ const l = this._d.getOptions();
2926
+ if ((e.ctrlKey || e.metaKey) && l.draggable && t.focusCell) {
2927
+ if (e.key === "ArrowDown") {
2928
+ e.preventDefault();
2929
+ const r = t.focusCell.ci !== void 0 ? t.focusCell.ri : 0;
2930
+ r < i - 1 && (this._d.handleRowDrop(r, r + 1), this._d.setFocusCell(r + 1, t.focusCell.ci), this._d.announce(`행 ${r + 1}을(를) ${r + 2}번째 위치로 이동`));
2931
+ return;
2932
+ }
2933
+ if (e.key === "ArrowUp") {
2934
+ e.preventDefault();
2935
+ const r = t.focusCell.ri;
2936
+ r > 0 && (this._d.handleRowDrop(r, r - 1), this._d.setFocusCell(r - 1, t.focusCell.ci), this._d.announce(`행 ${r + 1}을(를) ${r}번째 위치로 이동`));
2937
+ return;
2938
+ }
2939
+ }
2940
+ switch (e.key) {
2941
+ case "ArrowDown": {
2942
+ e.preventDefault();
2943
+ const r = t.focusCell, a = r ? Math.min(r.ri + 1, i - 1) : 0;
2944
+ this._d.setFocusCell(a, (r == null ? void 0 : r.ci) ?? 0);
2945
+ break;
2946
+ }
2947
+ case "ArrowUp": {
2948
+ e.preventDefault();
2949
+ const r = t.focusCell, a = r ? Math.max(r.ri - 1, 0) : 0;
2950
+ this._d.setFocusCell(a, (r == null ? void 0 : r.ci) ?? 0);
2951
+ break;
2952
+ }
2953
+ case "ArrowRight": {
2954
+ e.preventDefault();
2955
+ const r = t.focusCell;
2956
+ if (!r) {
2957
+ this._d.setFocusCell(0, 0);
2958
+ break;
2959
+ }
2960
+ r.ci < o - 1 ? this._d.setFocusCell(r.ri, r.ci + 1) : r.ri < i - 1 && this._d.setFocusCell(r.ri + 1, 0);
2961
+ break;
2962
+ }
2963
+ case "ArrowLeft": {
2964
+ e.preventDefault();
2965
+ const r = t.focusCell;
2966
+ if (!r) {
2967
+ this._d.setFocusCell(0, 0);
2968
+ break;
2969
+ }
2970
+ r.ci > 0 ? this._d.setFocusCell(r.ri, r.ci - 1) : r.ri > 0 && this._d.setFocusCell(r.ri - 1, o - 1);
2971
+ break;
2972
+ }
2973
+ case "Tab": {
2974
+ e.preventDefault();
2975
+ const r = t.focusCell;
2976
+ if (!r) {
2977
+ this._d.setFocusCell(0, 0);
2978
+ break;
2979
+ }
2980
+ 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 < i - 1 && this._d.setFocusCell(r.ri + 1, 0);
2981
+ break;
2982
+ }
2983
+ case "Home": {
2984
+ if (e.preventDefault(), e.ctrlKey || e.metaKey)
2985
+ this._d.setFocusCell(0, 0);
2986
+ else {
2987
+ const r = t.focusCell;
2988
+ this._d.setFocusCell((r == null ? void 0 : r.ri) ?? 0, 0);
2989
+ }
2990
+ break;
2991
+ }
2992
+ case "End": {
2993
+ if (e.preventDefault(), e.ctrlKey || e.metaKey)
2994
+ this._d.setFocusCell(i - 1, o - 1);
2995
+ else {
2996
+ const r = t.focusCell;
2997
+ this._d.setFocusCell((r == null ? void 0 : r.ri) ?? 0, o - 1);
2998
+ }
2999
+ break;
3000
+ }
3001
+ case "PageDown": {
3002
+ e.preventDefault();
3003
+ const r = t.focusCell, a = this._d.getOptions().pageSize ?? 10, c = Math.min(r ? r.ri + a : a - 1, i - 1);
3004
+ this._d.setFocusCell(c, (r == null ? void 0 : r.ci) ?? 0);
3005
+ break;
3006
+ }
3007
+ case "PageUp": {
3008
+ e.preventDefault();
3009
+ const r = t.focusCell, a = this._d.getOptions().pageSize ?? 10, c = r ? Math.max(r.ri - a, 0) : 0;
3010
+ this._d.setFocusCell(c, (r == null ? void 0 : r.ci) ?? 0);
3011
+ break;
3012
+ }
3013
+ case " ": {
3014
+ if (t.focusCell) {
3015
+ e.preventDefault();
3016
+ const r = t.focusCell.ri, a = this._d.getRowMgr();
3017
+ this._d.getOptions().checkColumn ? (a.check(r, !a.checkedRows.has(r)), this._d.doRender()) : (a.selectToggle(r), this._d.doRender());
3018
+ }
3019
+ break;
3020
+ }
3021
+ case "F2":
3022
+ case "Enter": {
3023
+ t.focusCell && this._d.getOptions().editable && (e.preventDefault(), t.startEditByKey(t.focusCell.ri, t.focusCell.ci));
3024
+ break;
3025
+ }
3026
+ case "Escape": {
3027
+ t.clearFocusCell(), this._d.doRender();
3028
+ break;
3029
+ }
3030
+ }
3031
+ }
3032
+ _copyToClipboard() {
3033
+ var o;
3034
+ if (!this._d.getOptions().clipboard) return;
3035
+ const t = this._d.getEditMgr(), s = this._d.getColLayout(), n = this._d.getData();
3036
+ let i = "";
3037
+ if (t.focusCell) {
3038
+ const { ri: l, ci: r } = t.focusCell, a = s.visibleLeaves[r];
3039
+ a && (i = String(n.getCellValue(l, a.field) ?? ""));
3040
+ } else if (this._d.getRowMgr().selectedRows.size > 0) {
3041
+ const l = s.visibleLeaves;
3042
+ i = [...this._d.getRowMgr().selectedRows].sort((a, c) => a - c).map((a) => {
3043
+ const c = n.getRowByIndex(a);
3044
+ return l.map((h) => String((c == null ? void 0 : c[h.field]) ?? "")).join(" ");
3045
+ }).join(`
3046
+ `);
3047
+ }
3048
+ i && ((o = navigator.clipboard) == null || o.writeText(i).catch(() => {
3049
+ }));
3050
+ }
3051
+ _pasteFromClipboard() {
3052
+ var s;
3053
+ const e = this._d.getOptions();
3054
+ if (!e.clipboard || !e.editable) return;
3055
+ const t = this._d.getEditMgr();
3056
+ t.focusCell && ((s = navigator.clipboard) == null || s.readText().then((n) => {
3057
+ if (!n) return;
3058
+ const { ri: i, ci: o } = t.focusCell, l = n.split(`
3059
+ `), r = this._d.getColLayout().visibleLeaves, a = this._d.getData();
3060
+ for (let c = 0; c < l.length; c++) {
3061
+ const h = l[c].split(" ");
3062
+ for (let u = 0; u < h.length; u++) {
3063
+ const g = i + c, E = o + u, w = r[E];
3064
+ w && g < a.rowCount && a.updateCell(g, w.field, h[u]);
3065
+ }
3066
+ }
3067
+ this._d.emit("dataChange", a.getData()), this._d.doRender();
3068
+ }).catch(() => {
3069
+ }));
3070
+ }
3071
+ }
3072
+ class Ht {
3073
+ constructor(e) {
3074
+ this._bar = null, this._input = null, this._count = null, this._filter = "", this._d = e;
3075
+ }
3076
+ get findFilter() {
3077
+ return this._filter;
3078
+ }
3079
+ init(e) {
3080
+ const t = document.createElement("div");
3081
+ t.className = "og-find-bar", t.hidden = !0;
3082
+ const s = document.createElement("span");
3083
+ s.className = "og-find-label", s.textContent = "찾기";
3084
+ const n = document.createElement("input");
3085
+ n.type = "text", n.className = "og-find-input", n.placeholder = "검색어 입력...", n.setAttribute("aria-label", "그리드 내 검색");
3086
+ const i = document.createElement("span");
3087
+ i.className = "og-find-count";
3088
+ const o = document.createElement("button");
3089
+ o.className = "og-find-close", o.textContent = "✕", o.setAttribute("aria-label", "찾기 닫기"), t.appendChild(s), t.appendChild(n), t.appendChild(i), t.appendChild(o), e.insertBefore(t, e.firstChild), n.addEventListener("input", () => {
3090
+ this._filter = n.value.trim(), this._apply();
3091
+ }), n.addEventListener("keydown", (l) => {
3092
+ l.key === "Escape" && this.close();
3093
+ }), o.addEventListener("click", () => this.close()), this._bar = t, this._input = n, this._count = i;
3094
+ }
3095
+ open() {
3096
+ this._bar && (this._bar.hidden = !1, this._input.focus(), this._input.select());
3097
+ }
3098
+ close() {
3099
+ this._bar && (this._bar.hidden = !0, this._filter = "", this._input.value = "", this._count && (this._count.textContent = ""), this._apply());
3100
+ }
3101
+ _apply() {
3102
+ var n, i;
3103
+ const e = this._d.getData(), t = this._d.getColLayout().visibleLeaves.map((o) => o.field);
3104
+ e.setFindFilter(this._filter, t), e.applyFilter(this._d.getFilters());
3105
+ const s = e.rowCount;
3106
+ (n = this._d.getVs()) == null || n.setTotalRows(s), (i = this._d.getPagination()) == null || i.setTotalRows(s), this._count && (this._count.textContent = this._filter ? `${s}건` : ""), this._d.doRender();
3107
+ }
3108
+ }
3109
+ function Ne(d) {
3110
+ return d && d._isGroup === !0;
3111
+ }
3112
+ function Ie(d, e, t = [], s = /* @__PURE__ */ new Set(), n) {
3113
+ return e.length ? Ke(d, e, 0, t, s, "", n) : [];
3114
+ }
3115
+ function Ke(d, e, t, s, n, i, o) {
3116
+ const l = e[t], r = /* @__PURE__ */ new Map();
3117
+ for (const c of d) {
3118
+ const h = c[l];
3119
+ r.has(h) || r.set(h, []), r.get(h).push(c);
3120
+ }
3121
+ const a = [];
3122
+ for (const [c, h] of r) {
3123
+ const u = `${i}__${l}:${c}`, g = n.has(u);
3124
+ let E;
3125
+ t < e.length - 1 ? E = Ke(h, e, t + 1, s, n, u, o) : E = h;
3126
+ const { summary: w, summaryFmt: C } = Bt(h, s), M = Wt(h, o);
3127
+ a.push({
3128
+ _isGroup: !0,
3129
+ _groupField: l,
3130
+ _groupValue: c,
3131
+ _groupLabel: c == null ? "(없음)" : String(c),
3132
+ _depth: t,
3133
+ _expanded: g,
3134
+ _childCount: h.length,
3135
+ _summary: w,
3136
+ _summaryFmt: C,
3137
+ _states: M,
3138
+ children: E
3139
+ });
3140
+ }
3141
+ return a;
3142
+ }
3143
+ function Bt(d, e) {
3144
+ const t = {}, s = {};
3145
+ for (const n of e) {
3146
+ const i = d.map((a) => a[n.field]).filter((a) => a != null && a !== "");
3147
+ let o = null;
3148
+ const l = n.op.toUpperCase();
3149
+ if (l === "SUM")
3150
+ o = i.length > 0 ? x.sum(i.map(String)) : null;
3151
+ else if (l === "AVG")
3152
+ o = i.length > 0 ? x.sum(i.map(String)).div(x.from(String(i.length))) : null;
3153
+ else if (l === "COUNT") {
3154
+ t[n.field] = d.length, s[n.field] = d.length.toLocaleString("ko-KR");
3155
+ continue;
3156
+ } else l === "MAX" ? o = i.length > 0 ? x.max(i.map(String)) : null : l === "MIN" && (o = i.length > 0 ? x.min(i.map(String)) : null);
3157
+ if (!o) {
3158
+ t[n.field] = null, s[n.field] = "";
3159
+ continue;
3160
+ }
3161
+ const r = o.toNumber();
3162
+ t[n.field] = r, s[n.field] = Nt(r, n.format);
3163
+ }
3164
+ return { summary: t, summaryFmt: s };
3165
+ }
3166
+ function Wt(d, e) {
3167
+ if (!e) return { added: 0, edited: 0, removed: 0 };
3168
+ let t = 0, s = 0, n = 0;
3169
+ for (const i of d) {
3170
+ const o = e(i);
3171
+ o === "added" ? t++ : o === "edited" ? s++ : o === "removed" && n++;
3172
+ }
3173
+ return { added: t, edited: s, removed: n };
3174
+ }
3175
+ function Nt(d, e) {
3176
+ if (e == null)
3177
+ return d % 1 === 0 ? d.toLocaleString("ko-KR") : parseFloat(d.toFixed(6)).toLocaleString("ko-KR", {
3178
+ minimumFractionDigits: 2,
3179
+ maximumFractionDigits: 6
3180
+ });
3181
+ const t = e.includes("#") || e.includes(","), s = e.match(/\.(\d+)$/), n = s ? parseInt(s[1], 10) : /^\d+$/.test(e) ? parseInt(e, 10) : 0, i = Math.abs(d).toFixed(n), [o = "0", l] = i.split("."), r = t ? o.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : o, a = l !== void 0 ? `${r}.${l}` : r;
3182
+ return d < 0 ? `-${a}` : a;
3183
+ }
3184
+ function Oe(d) {
3185
+ const e = [];
3186
+ for (const t of d)
3187
+ if (e.push(t), t._expanded)
3188
+ for (const s of t.children)
3189
+ Ne(s) ? e.push(...Oe([s])) : e.push(s);
3190
+ return e;
3191
+ }
3192
+ function Ve(d, e = "") {
3193
+ const t = [];
3194
+ for (const s of d) {
3195
+ const n = `${e}__${s._groupField}:${s._groupValue}`;
3196
+ t.push(n);
3197
+ const i = s.children.filter((o) => Ne(o));
3198
+ i.length && t.push(...Ve(i, n));
3199
+ }
3200
+ return t;
3201
+ }
3202
+ function He(d, e, t = /* @__PURE__ */ new Set()) {
3203
+ const { idField: s, parentIdField: n, expandOnLoad: i = !1 } = e, o = /* @__PURE__ */ new Map(), l = [];
3204
+ for (const c of d) {
3205
+ const h = c[s], u = {
3206
+ _isTree: !0,
3207
+ _treeId: h,
3208
+ _treeParentId: c[n],
3209
+ _depth: 0,
3210
+ _expanded: i || t.has(h),
3211
+ _hasChildren: !1,
3212
+ _childCount: 0,
3213
+ _isLastChild: !1,
3214
+ _ancestorHasMore: [],
3215
+ data: c,
3216
+ children: []
3217
+ };
3218
+ o.set(h, u);
3219
+ }
3220
+ for (const c of o.values()) {
3221
+ const h = c._treeParentId;
3222
+ if (h == null || h === "" || !o.has(h))
3223
+ l.push(c);
3224
+ else {
3225
+ const g = o.get(h);
3226
+ g.children.push(c), g._hasChildren = !0;
3227
+ }
3228
+ }
3229
+ function r(c, h) {
3230
+ for (const u of c)
3231
+ u._depth = h, u._childCount = Pe(u), r(u.children, h + 1);
3232
+ }
3233
+ r(l, 0);
3234
+ function a(c, h) {
3235
+ for (let u = 0; u < c.length; u++) {
3236
+ const g = c[u], E = u === c.length - 1;
3237
+ g._isLastChild = E, g._ancestorHasMore = h, g.children.length > 0 && a(g.children, [...h, !E]);
3238
+ }
3239
+ }
3240
+ return a(l, []), l;
3241
+ }
3242
+ function Pe(d) {
3243
+ let e = d.children.length;
3244
+ for (const t of d.children) e += Pe(t);
3245
+ return e;
3246
+ }
3247
+ function Ue(d) {
3248
+ const e = [];
3249
+ for (const t of d)
3250
+ e.push(t), t._expanded && t.children.length > 0 && e.push(...Ue(t.children));
3251
+ return e;
3252
+ }
3253
+ function Kt(d, e) {
3254
+ d.has(e) ? d.delete(e) : d.add(e);
3255
+ }
3256
+ function ve(d) {
3257
+ const e = [];
3258
+ for (const t of d)
3259
+ e.push(t._treeId), t.children.length && e.push(...ve(t.children));
3260
+ return e;
3261
+ }
3262
+ class Ot {
3263
+ constructor(e) {
3264
+ 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;
3265
+ }
3266
+ // ─── 상태 접근자 ─────────────────────────────────────────
3267
+ get isGroupMode() {
3268
+ return this._isGroupMode;
3269
+ }
3270
+ get isTreeMode() {
3271
+ return this._isTreeMode;
3272
+ }
3273
+ get groupFlatRows() {
3274
+ return this._groupFlatRows;
3275
+ }
3276
+ get treeFlatRows() {
3277
+ return this._treeFlatRows;
3278
+ }
3279
+ // ─── 그룹 ─────────────────────────────────────────────────
3280
+ groupBy(e) {
3281
+ this._groupFields = e, this._groupExpandedKeys.clear(), this._isGroupMode = e.length > 0, this.rebuildGroups();
3282
+ }
3283
+ clearGroup() {
3284
+ var t;
3285
+ this._groupFields = [], this._groupExpandedKeys.clear(), this._isGroupMode = !1, this._groupFlatRows = [];
3286
+ const e = this._d.getData().length;
3287
+ (t = this._d.getVs()) == null || t.setTotalRows(e), this._d.doRender();
3288
+ }
3289
+ expandAll() {
3290
+ if (!this._isGroupMode) return;
3291
+ const e = Ie(this._d.getData(), this._groupFields, this._getSummaryDefs());
3292
+ Ve(e).forEach((t) => this._groupExpandedKeys.add(t)), this.rebuildGroups();
3293
+ }
3294
+ collapseAll() {
3295
+ this._groupExpandedKeys.clear(), this._isGroupMode && this.rebuildGroups();
3296
+ }
3297
+ handleGroupToggle(e) {
3298
+ this._groupExpandedKeys.has(e) ? this._groupExpandedKeys.delete(e) : this._groupExpandedKeys.add(e), this.rebuildGroups();
3299
+ }
3300
+ rebuildGroups() {
3301
+ var i;
3302
+ const e = this._d.getData(), t = this._d.getDataLayer(), s = (o) => {
3303
+ const l = e.indexOf(o);
3304
+ return l >= 0 ? t.getRowState(l) : "none";
3305
+ }, n = Ie(e, this._groupFields, this._getSummaryDefs(), this._groupExpandedKeys, s);
3306
+ this._groupFlatRows = Oe(n), (i = this._d.getVs()) == null || i.setTotalRows(this._groupFlatRows.length), this._d.doRenderFull(this._groupFlatRows.length);
3307
+ }
3308
+ // ─── 트리 ─────────────────────────────────────────────────
3309
+ enableTree() {
3310
+ this._isTreeMode = !0, this._isGroupMode = !1;
3311
+ const e = this._d.getOptions();
3312
+ if (e.expandOnLoad) {
3313
+ const t = He(this._d.getData(), {
3314
+ idField: e.treeId,
3315
+ parentIdField: e.treeParentId
3316
+ });
3317
+ ve(t).forEach((s) => this._treeExpandedKeys.add(s));
3318
+ }
3319
+ this.rebuildTree();
3320
+ }
3321
+ disableTree() {
3322
+ var t;
3323
+ this._isTreeMode = !1, this._treeRoots = [], this._treeFlatRows = [], this._treeExpandedKeys.clear();
3324
+ const e = this._d.getData().length;
3325
+ (t = this._d.getVs()) == null || t.setTotalRows(e), this._d.doRender();
3326
+ }
3327
+ expandNodes(e, t = !0) {
3328
+ const s = Array.isArray(e) ? e : [e];
3329
+ for (const n of s)
3330
+ t ? this._treeExpandedKeys.add(n) : this._treeExpandedKeys.delete(n);
3331
+ this._isTreeMode && this.rebuildTree();
3332
+ }
3333
+ expandAllNodes() {
3334
+ this._isTreeMode && (ve(this._treeRoots).forEach((e) => this._treeExpandedKeys.add(e)), this.rebuildTree());
3335
+ }
3336
+ collapseAllNodes() {
3337
+ this._isTreeMode && (this._treeExpandedKeys.clear(), this.rebuildTree());
3338
+ }
3339
+ handleTreeToggle(e) {
3340
+ Kt(this._treeExpandedKeys, e), this.rebuildTree();
3341
+ }
3342
+ rebuildTree() {
3343
+ var t;
3344
+ const e = this._d.getOptions();
3345
+ this._treeRoots = He(this._d.getData(), {
3346
+ idField: e.treeId,
3347
+ parentIdField: e.treeParentId,
3348
+ expandOnLoad: e.expandOnLoad
3349
+ }, this._treeExpandedKeys), this._treeFlatRows = Ue(this._treeRoots), (t = this._d.getVs()) == null || t.setTotalRows(this._treeFlatRows.length), this._d.doRenderFull(this._treeFlatRows.length);
3350
+ }
3351
+ // ─── 내부 헬퍼 ───────────────────────────────────────────
3352
+ _getSummaryDefs() {
3353
+ const e = this._d.getOptions().summary;
3354
+ if (!e) return [];
3355
+ if (e.rows && e.rows.length > 0)
3356
+ return e.fields.flatMap(
3357
+ (s) => e.rows.map((n) => ({ field: s, op: n.op, format: n.format }))
3358
+ );
3359
+ const t = Array.isArray(e.ops) ? e.ops : e.ops ? [e.ops] : ["SUM"];
3360
+ return e.fields.map((s) => ({ field: s, op: t[0] ?? "SUM", format: e.format }));
3361
+ }
3362
+ }
3363
+ class Vt {
3364
+ constructor(e) {
3365
+ this._sortList = [], this._filters = {}, this._d = e;
3366
+ }
3367
+ // ─── 상태 접근자 ─────────────────────────────────────────
3368
+ get sortList() {
3369
+ return this._sortList;
3370
+ }
3371
+ get filters() {
3372
+ return this._filters;
3373
+ }
3374
+ // ─── 정렬 ─────────────────────────────────────────────────
3375
+ handleSortClick(e, t) {
3376
+ var l;
3377
+ const s = this._d.getOptions();
3378
+ if (!s.sortable) return;
3379
+ const n = this._sortList.findIndex((r) => r.field === e);
3380
+ if (n >= 0) {
3381
+ const r = this._sortList[n];
3382
+ r.dir === "asc" ? r.dir = "desc" : this._sortList.splice(n, 1);
3383
+ } else
3384
+ (!t || !s.multiSort) && (this._sortList = []), this._sortList.push({ field: e, dir: "asc" });
3385
+ this._d.getData().applySort(this._sortList), this._d.renderHeader(), this._d.doRender();
3386
+ const i = this._sortList.find((r) => r.field === e), o = i ? i.dir === "asc" ? "오름차순" : "내림차순" : "정렬 해제";
3387
+ this._d.announce(`${e} ${o} 정렬`), this._d.emit("sortChange", { sortList: this._sortList }), (l = s.onSortChange) == null || l.call(s, { field: e, dir: (i == null ? void 0 : i.dir) ?? "asc", sortList: this._sortList });
3388
+ }
3389
+ sort(e, t = "asc") {
3390
+ if (Array.isArray(e))
3391
+ this._sortList = e;
3392
+ else {
3393
+ const s = this._sortList.findIndex((n) => n.field === e);
3394
+ s >= 0 ? this._sortList[s].dir = t : this._sortList = [{ field: e, dir: t }], this._d.getOptions().multiSort || (this._sortList = this._sortList.slice(-1));
3395
+ }
3396
+ this._d.getData().applySort(this._sortList), this._d.renderHeader(), this._d.doRender(), this._d.emit("sortChange", { sortList: this._sortList });
3397
+ }
3398
+ resetSort() {
3399
+ this._sortList = [], this._d.getData().applySort([]), this._d.renderHeader(), this._d.doRender();
3400
+ }
3401
+ initSort(e) {
3402
+ this._sortList = [...e], this._d.getData().applySort(this._sortList);
3403
+ }
3404
+ getSortState() {
3405
+ return [...this._sortList];
3406
+ }
3407
+ // ─── 필터 ─────────────────────────────────────────────────
3408
+ setFilter(e, t) {
3409
+ var s, n;
3410
+ this._filters[e] = t, this.applyFilters(), this._d.renderHeader(), this._d.doRender(), this._d.emit("filterChange", { field: e, filterItems: t, allFilters: this._filters }), (n = (s = this._d.getOptions()).onFilterChange) == null || n.call(s, { field: e, filterItems: t, allFilters: this._filters });
3411
+ }
3412
+ resetFilter(e) {
3413
+ e ? delete this._filters[e] : this._filters = {}, this.applyFilters(), this._d.renderHeader(), this._d.doRender();
3414
+ }
3415
+ getFilterState() {
3416
+ return { ...this._filters };
3417
+ }
3418
+ restoreFilter(e) {
3419
+ this._filters = { ...e }, this.applyFilters();
3420
+ }
3421
+ applyFilters() {
3422
+ var s, n;
3423
+ const e = this._d.getData();
3424
+ e.setFindFilter(this._d.getFindFilter(), this._d.getColLayout().visibleLeaves.map((i) => i.field)), e.applyFilter(this._filters);
3425
+ const t = e.rowCount;
3426
+ (s = this._d.getVs()) == null || s.setTotalRows(t), (n = this._d.getPagination()) == null || n.setTotalRows(t);
3427
+ }
3428
+ }
3429
+ class Pt {
3430
+ constructor(e) {
3431
+ this._d = e;
3432
+ }
3433
+ handleCellClick(e, t, s) {
3434
+ var a, c, h, u, g, E, w;
3435
+ const n = this._d.getOptions(), i = this._d.getRowMgr(), o = this._d.getEditMgr();
3436
+ n.selection === "single" || n.selection === "row" ? i.selectSingle(e) : n.selection === "multiple" && (s.ctrlKey || s.metaKey ? i.selectToggle(e) : i.selectSingle(e));
3437
+ const l = this._d.getData().getRowByIndex(e), r = this._d.getColLayout().visibleLeaves[t];
3438
+ if (l && r) {
3439
+ const C = r.editable !== !1 && (r.editable !== void 0 || n.editable);
3440
+ if (Z(r) && C) {
3441
+ const F = l[r.field];
3442
+ this._d.writeCell(e, r.field, !F);
3443
+ }
3444
+ if (r.type === "radio") {
3445
+ const F = r.group;
3446
+ for (const A of this._d.getColLayout().visibleLeaves)
3447
+ A.type === "radio" && A.field !== r.field && (!F || A.group === F) && this._d.getData().updateCell(e, A.field, !1);
3448
+ this._d.writeCell(e, r.field, !0);
3449
+ }
3450
+ const M = {
3451
+ type: "cellClick",
3452
+ rowIndex: e,
3453
+ columnIndex: t,
3454
+ field: r.field,
3455
+ value: l[r.field],
3456
+ row: l,
3457
+ column: r,
3458
+ target: s.target,
3459
+ originalEvent: s
3460
+ };
3461
+ this._d.emit("cellClick", M), (a = n.onCellClick) == null || a.call(n, M);
3462
+ const p = { type: "rowClick", rowIndex: e, row: l, target: s.target, originalEvent: s };
3463
+ this._d.emit("rowClick", p), (c = n.onRowClick) == null || c.call(n, p);
3464
+ const v = r.type === "select";
3465
+ !(o.activeEditor != null && ((h = o.editCell) == null ? void 0 : h.ri) === e && ((u = o.editCell) == null ? void 0 : u.ci) === t) && (n.editMode === "click" || v) && !Z(r) && o.startEdit(e, t, s);
3466
+ }
3467
+ 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", {
3468
+ rows: i.getSelections(),
3469
+ rowIndexes: [...i.selectedRows]
3470
+ }), (w = n.onSelectionChange) == null || w.call(n, { rows: i.getSelections(), rowIndexes: [...i.selectedRows], cells: [] }));
3471
+ }
3472
+ handleCellDblClick(e, t, s) {
3473
+ var a, c;
3474
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3475
+ if (!n || !i) return;
3476
+ const o = this._d.getOptions(), l = {
3477
+ type: "cellDblClick",
3478
+ rowIndex: e,
3479
+ columnIndex: t,
3480
+ field: i.field,
3481
+ value: n[i.field],
3482
+ row: n,
3483
+ column: i,
3484
+ target: s.target,
3485
+ originalEvent: s
3486
+ };
3487
+ this._d.emit("cellDblClick", l), (a = o.onCellDblClick) == null || a.call(o, l);
3488
+ const r = { type: "rowDblClick", rowIndex: e, row: n, target: s.target, originalEvent: s };
3489
+ this._d.emit("rowDblClick", r), (c = o.onRowDblClick) == null || c.call(o, r), o.editMode === "dblclick" && this._d.getEditMgr().startEdit(e, t, s);
3490
+ }
3491
+ handleCellMouseOver(e, t, s) {
3492
+ var a, c;
3493
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3494
+ if (!n || !i) return;
3495
+ const o = this._d.getOptions(), l = { type: "cellMouseOver", rowIndex: e, columnIndex: t, field: i.field, value: n[i.field], row: n, column: i, target: s.target, originalEvent: s };
3496
+ this._d.emit("cellMouseOver", l), (a = o.onCellMouseOver) == null || a.call(o, l);
3497
+ const r = { type: "rowMouseOver", rowIndex: e, row: n, target: s.target, originalEvent: s };
3498
+ this._d.emit("rowMouseOver", r), (c = o.onRowMouseOver) == null || c.call(o, r);
3499
+ }
3500
+ handleCellMouseOut(e, t, s) {
3501
+ var a, c;
3502
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3503
+ if (!n || !i) return;
3504
+ const o = this._d.getOptions(), l = { type: "cellMouseOut", rowIndex: e, columnIndex: t, field: i.field, value: n[i.field], row: n, column: i, target: s.target, originalEvent: s };
3505
+ this._d.emit("cellMouseOut", l), (a = o.onCellMouseOut) == null || a.call(o, l);
3506
+ const r = { type: "rowMouseOut", rowIndex: e, row: n, target: s.target, originalEvent: s };
3507
+ this._d.emit("rowMouseOut", r), (c = o.onRowMouseOut) == null || c.call(o, r);
3508
+ }
3509
+ handleCellMouseDown(e, t, s) {
3510
+ var a, c;
3511
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3512
+ if (!n || !i) return;
3513
+ const o = this._d.getOptions(), l = { type: "cellMouseDown", rowIndex: e, columnIndex: t, field: i.field, value: n[i.field], row: n, column: i, target: s.target, originalEvent: s };
3514
+ this._d.emit("cellMouseDown", l), (a = o.onCellMouseDown) == null || a.call(o, l);
3515
+ const r = { type: "rowMouseDown", rowIndex: e, row: n, target: s.target, originalEvent: s };
3516
+ this._d.emit("rowMouseDown", r), (c = o.onRowMouseDown) == null || c.call(o, r);
3517
+ }
3518
+ handleCellMouseUp(e, t, s) {
3519
+ var a, c;
3520
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3521
+ if (!n || !i) return;
3522
+ const o = this._d.getOptions(), l = { type: "cellMouseUp", rowIndex: e, columnIndex: t, field: i.field, value: n[i.field], row: n, column: i, target: s.target, originalEvent: s };
3523
+ this._d.emit("cellMouseUp", l), (a = o.onCellMouseUp) == null || a.call(o, l);
3524
+ const r = { type: "rowMouseUp", rowIndex: e, row: n, target: s.target, originalEvent: s };
3525
+ this._d.emit("rowMouseUp", r), (c = o.onRowMouseUp) == null || c.call(o, r);
3526
+ }
3527
+ handleCellMouseMove(e, t, s) {
3528
+ var a, c;
3529
+ const n = this._d.getData().getRowByIndex(e), i = this._d.getColLayout().visibleLeaves[t];
3530
+ if (!n || !i) return;
3531
+ const o = this._d.getOptions(), l = { type: "cellMouseMove", rowIndex: e, columnIndex: t, field: i.field, value: n[i.field], row: n, column: i, target: s.target, originalEvent: s };
3532
+ this._d.emit("cellMouseMove", l), (a = o.onCellMouseMove) == null || a.call(o, l);
3533
+ const r = { type: "rowMouseMove", rowIndex: e, row: n, target: s.target, originalEvent: s };
3534
+ this._d.emit("rowMouseMove", r), (c = o.onRowMouseMove) == null || c.call(o, r);
3535
+ }
3536
+ handleCellKeyEvt(e, t) {
3537
+ var c, h, u;
3538
+ const s = this._d.getEditMgr();
3539
+ if (!s.focusCell || s.activeEditor) return;
3540
+ const { ri: n, ci: i } = s.focusCell, o = this._d.getData().getRowByIndex(n), l = this._d.getColLayout().visibleLeaves[i];
3541
+ if (!o || !l) return;
3542
+ const r = this._d.getOptions(), a = { type: e, rowIndex: n, columnIndex: i, field: l.field, value: o[l.field], row: o, column: l, key: t.key, target: this._d.getContainer(), originalEvent: t };
3543
+ 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);
3544
+ }
3545
+ }
3546
+ class Ut {
3547
+ constructor() {
3548
+ this._triggers = /* @__PURE__ */ new Map();
3549
+ }
3550
+ add(e, t) {
3551
+ this._triggers.has(e) || this._triggers.set(e, []), this._triggers.get(e).push(t);
3552
+ }
3553
+ remove(e, t) {
3554
+ const s = this._triggers.get(e);
3555
+ if (s) {
3556
+ const n = s.indexOf(t);
3557
+ n >= 0 && s.splice(n, 1);
3558
+ }
3559
+ }
3560
+ clear(e) {
3561
+ e ? this._triggers.delete(e) : this._triggers.clear();
3562
+ }
3563
+ mkCtx(e, t) {
3564
+ let s = !1;
3565
+ return {
3566
+ operation: e,
3567
+ args: t,
3568
+ result: void 0,
3569
+ extra: {},
3570
+ timestamp: Date.now(),
3571
+ get cancelled() {
3572
+ return s;
3573
+ },
3574
+ cancel() {
3575
+ s = !0;
3576
+ }
3577
+ };
3578
+ }
3579
+ exec(e, t) {
3580
+ const s = this._triggers.get(e) ?? [];
3581
+ for (const n of s)
3582
+ if (n(t), t.cancelled) return !1;
3583
+ if (e.startsWith("after:")) {
3584
+ const n = this._triggers.get("complete") ?? [];
3585
+ for (const i of n) i(t);
3586
+ }
3587
+ return !0;
3588
+ }
3589
+ }
3590
+ const jt = "_ogRowId";
3591
+ class Xt extends qe {
3592
+ constructor(e, t) {
3593
+ var n;
3594
+ 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;
3595
+ const s = typeof e == "string" ? document.querySelector(e) : e;
3596
+ if (!s) throw new Error(`OpenGrid: container not found: ${e}`);
3597
+ this._container = s, this._options = {
3598
+ height: "100%",
3599
+ width: "100%",
3600
+ rowHeight: 32,
3601
+ headerHeight: 34,
3602
+ footerHeight: 30,
3603
+ autoHeight: !1,
3604
+ fillWidth: !1,
3605
+ defaultColumnWidth: 100,
3606
+ editable: !1,
3607
+ editMode: "dblclick",
3608
+ history: !0,
3609
+ historySize: 100,
3610
+ selection: "single",
3611
+ clipboard: !0,
3612
+ sortable: !0,
3613
+ multiSort: !0,
3614
+ filterable: !0,
3615
+ defaultSort: [],
3616
+ frozenColumns: 0,
3617
+ frozenRows: 0,
3618
+ rowNumber: !1,
3619
+ stateColumn: !1,
3620
+ checkColumn: !1,
3621
+ draggable: !1,
3622
+ mergeCells: !1,
3623
+ groupBy: [],
3624
+ summary: void 0,
3625
+ treeMode: "auto",
3626
+ treeId: "id",
3627
+ treeParentId: "parentId",
3628
+ expandOnLoad: !1,
3629
+ pagination: !1,
3630
+ pageSize: 50,
3631
+ footer: void 0,
3632
+ footerPosition: "bottom",
3633
+ theme: "default",
3634
+ cssVars: {},
3635
+ ariaLabel: "OPEN_GRID 데이터 그리드",
3636
+ ...t
3637
+ }, this._data = new Xe(jt), this._rowMgr = new kt(this._data), this._colLayout = new re(this._options.columns, this._options.frozenColumns), this._editMgr = new Et({
3638
+ data: this._data,
3639
+ colLayout: this._colLayout,
3640
+ getRenderer: () => this._renderer,
3641
+ getContainer: () => this._container,
3642
+ getOptions: () => this._options,
3643
+ emit: (i, ...o) => this.emit(i, ...o),
3644
+ doRender: () => this._doRender(...this._visRange()),
3645
+ announce: (i) => this._announce(i),
3646
+ writeCell: (i, o, l) => this.writeCell(i, o, l),
3647
+ scrollToRow: (i) => {
3648
+ var o;
3649
+ return (o = this._vs) == null ? void 0 : o.scrollToRow(i);
3650
+ },
3651
+ getVisibleLeaves: () => this._colLayout.visibleLeaves
3652
+ }), this._exportMgr = new At({
3653
+ getData: () => this._data.getData(),
3654
+ getColLayout: () => this._colLayout,
3655
+ getColWidths: () => this._colWidths,
3656
+ getOptions: () => this._options,
3657
+ getContainer: () => this._container,
3658
+ getMaskEnabled: (i) => this.getMaskEnabled(i),
3659
+ getWsManager: () => this._wsManager
3660
+ }), this._footerMgr = new zt({
3661
+ getData: () => this._data.getData(),
3662
+ getColLayout: () => this._colLayout,
3663
+ getColWidths: () => this._colWidths,
3664
+ getOptions: () => this._options,
3665
+ getContainer: () => this._container
3666
+ }), this._kbdMgr = new It({
3667
+ getEditMgr: () => this._editMgr,
3668
+ getRowMgr: () => this._rowMgr,
3669
+ getData: () => this._data,
3670
+ getColLayout: () => this._colLayout,
3671
+ getOptions: () => this._options,
3672
+ setFocusCell: (i, o) => this._setFocusCell(i, o),
3673
+ handleRowDrop: (i, o) => this._handleRowDrop(i, o),
3674
+ doRender: () => this._doRender(...this._visRange()),
3675
+ announce: (i) => this._announce(i),
3676
+ emit: (i, ...o) => this.emit(i, ...o),
3677
+ visRange: () => this._visRange(),
3678
+ handleCellKeyEvt: (i, o) => this._handleCellKeyEvt(i, o)
3679
+ }), this._sfMgr = new Vt({
3680
+ getData: () => this._data,
3681
+ getColLayout: () => this._colLayout,
3682
+ getFindFilter: () => this._findMgr.findFilter,
3683
+ getVs: () => this._vs,
3684
+ getPagination: () => this._pagination,
3685
+ getOptions: () => this._options,
3686
+ renderHeader: () => this._renderHeader(),
3687
+ doRender: () => this._doRender(...this._visRange()),
3688
+ announce: (i) => this._announce(i),
3689
+ emit: (i, ...o) => this.emit(i, ...o)
3690
+ }), this._findMgr = new Ht({
3691
+ getColLayout: () => this._colLayout,
3692
+ getData: () => this._data,
3693
+ getFilters: () => this._sfMgr.filters,
3694
+ getVs: () => this._vs,
3695
+ getPagination: () => this._pagination,
3696
+ doRender: () => this._doRender(...this._visRange())
3697
+ }), this._cellEvt = new Pt({
3698
+ getData: () => this._data,
3699
+ getColLayout: () => this._colLayout,
3700
+ getOptions: () => this._options,
3701
+ getEditMgr: () => this._editMgr,
3702
+ getRowMgr: () => this._rowMgr,
3703
+ emit: (i, ...o) => this.emit(i, ...o),
3704
+ writeCell: (i, o, l) => this.writeCell(i, o, l),
3705
+ doRender: () => this._doRender(...this._visRange()),
3706
+ getContainer: () => this._container
3707
+ }), this._grpMgr = new Ot({
3708
+ getData: () => this._data.getData(),
3709
+ getDataLayer: () => this._data,
3710
+ getOptions: () => this._options,
3711
+ getVs: () => this._vs,
3712
+ doRenderFull: (i) => this._doRender(0, i - 1),
3713
+ doRender: () => this._doRender(...this._visRange())
3714
+ }), this._mount(), this._bindOptionEvents(), (n = this._options.defaultSort) != null && n.length && this._sfMgr.initSort(this._options.defaultSort), requestAnimationFrame(() => {
3715
+ var i, o;
3716
+ this.emit("ready", this), (o = (i = this._options).onReady) == null || o.call(i, this);
3717
+ });
3718
+ }
3719
+ _mount() {
3720
+ var s, n;
3721
+ this._container.classList.add("og-container");
3722
+ const e = this._options.height, t = this._options.width;
3723
+ 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);
3724
+ for (const [i, o] of Object.entries(this._options.cssVars))
3725
+ this._container.style.setProperty(i, o);
3726
+ this._renderer = new Mt(this._container, this._options, {
3727
+ onHeaderClick: (i, o) => this._handleSortClick(i, o),
3728
+ onCellClick: (i, o, l) => this._handleCellClick(i, o, l),
3729
+ onCellDblClick: (i, o, l) => this._handleCellDblClick(i, o, l),
3730
+ onCellMouseOver: (i, o, l) => this._handleCellMouseOver(i, o, l),
3731
+ onCellMouseOut: (i, o, l) => this._handleCellMouseOut(i, o, l),
3732
+ onCellMouseDown: (i, o, l) => this._handleCellMouseDown(i, o, l),
3733
+ onCellMouseUp: (i, o, l) => this._handleCellMouseUp(i, o, l),
3734
+ onCellMouseMove: (i, o, l) => this._handleCellMouseMove(i, o, l),
3735
+ onRowCheck: (i, o) => this._handleRowCheck(i, o),
3736
+ onAllCheck: (i) => this._handleAllCheck(i),
3737
+ onColResize: (i, o) => this._handleColResize(i, o),
3738
+ onFilterIconClick: (i, o) => this._handleFilterIconClick(i, o),
3739
+ getDndManager: () => this._dnd,
3740
+ onColDragStart: (i) => {
3741
+ this._editMgr.dragColIdx = i;
3742
+ },
3743
+ onColDrop: (i) => {
3744
+ this._editMgr.dragColIdx !== null && this._editMgr.dragColIdx !== i && this._reorderColumn(this._editMgr.dragColIdx, i), this._editMgr.dragColIdx = null;
3745
+ },
3746
+ getColDragIdx: () => this._editMgr.dragColIdx
3747
+ }), this._filterPanel = new Je(
3748
+ this._container,
3749
+ (i, o) => this.setFilter(i, o),
3750
+ (i) => this.resetFilter(i)
3751
+ ), 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((i) => !i.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", (i) => this._handleKeyDown(i)), this._container.addEventListener("keyup", (i) => this._handleCellKeyEvt("cellKeyUp", i)), this._container.addEventListener("keypress", (i) => this._handleCellKeyEvt("cellKeyPress", i)), this._vs = new Qe(this._renderer.bodyWrapper, {
3752
+ rowHeight: this._options.rowHeight,
3753
+ onRender: (i, o) => this._doRender(i, o)
3754
+ }), this._options.draggable && (this._dnd = new Tt(
3755
+ this._renderer.bodyWrapper,
3756
+ this._options.rowHeight,
3757
+ (i, o) => this._handleRowDrop(i, o)
3758
+ )), this._options.pagination && (this._pagination = new Lt(
3759
+ this._container,
3760
+ this._options.pageSize,
3761
+ (i) => {
3762
+ this.emit("pageChange", i), this._doRender(...this._visRange());
3763
+ }
3764
+ )), this._findMgr.init(this._container), this._initContextMenu(), (n = this._options.worksheets) != null && n.length && this._initWorksheets(), this._ro = new ResizeObserver(() => this._onResize()), this._ro.observe(this._container), this._onResize();
3765
+ }
3766
+ _initContextMenu() {
3767
+ const e = this._options.contextMenu;
3768
+ 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, {
3769
+ onSortAsc: () => {
3770
+ const t = this._colLayout.visibleLeaves[0];
3771
+ t && this.orderBy(t.field, "asc");
3772
+ },
3773
+ onSortDesc: () => {
3774
+ const t = this._colLayout.visibleLeaves[0];
3775
+ t && this.orderBy(t.field, "desc");
3776
+ },
3777
+ onFind: () => this._findMgr.open(),
3778
+ onExcel: () => this.exportExcel(),
3779
+ onCsv: () => this.exportCsv(),
3780
+ onPrint: () => this.print()
3781
+ }), this._cmHandler = (t) => {
3782
+ var l;
3783
+ const s = t.target.closest(".og-cell");
3784
+ if (!s) return;
3785
+ t.preventDefault();
3786
+ const n = Number(s.dataset.colIndex ?? -1), i = this._colLayout.visibleLeaves[n];
3787
+ i && this._ctxMenu && (this._ctxMenu._actions.onSortAsc = () => this.orderBy(i.field, "asc"), this._ctxMenu._actions.onSortDesc = () => this.orderBy(i.field, "desc"));
3788
+ const o = Array.isArray(e) ? e : void 0;
3789
+ (l = this._ctxMenu) == null || l.open(t, o);
3790
+ }, this._container.addEventListener("contextmenu", this._cmHandler), this._cmKbdHandler = (t) => {
3791
+ var s;
3792
+ if (t.shiftKey && t.key === "F10") {
3793
+ t.preventDefault();
3794
+ const n = this._container.getBoundingClientRect(), i = { clientX: n.left + 80, clientY: n.top + 40 };
3795
+ (s = this._ctxMenu) == null || s.open(i);
3796
+ }
3797
+ }, this._container.addEventListener("keydown", this._cmKbdHandler));
3798
+ }
3799
+ // openContextMenu / closeContextMenu 공개 API
3800
+ openContextMenu(e, t) {
3801
+ var s;
3802
+ (s = this._ctxMenu) == null || s.open(e, t);
3803
+ }
3804
+ closeContextMenu() {
3805
+ var e;
3806
+ (e = this._ctxMenu) == null || e.close();
3807
+ }
3808
+ setFilterSelect(e) {
3809
+ var t;
3810
+ (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(
3811
+ this._container,
3812
+ e,
3813
+ (s, n) => this.setFilter(s, n),
3814
+ (s) => this.resetFilter(s),
3815
+ this._container.id
3816
+ ));
3817
+ }
3818
+ // 옵션을 런타임에 바꿀 때 호출 (contextMenu 재초기화, groupBy 재구성 등)
3819
+ setOptions(e) {
3820
+ var t;
3821
+ 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) {
3822
+ const s = e.groupBy ?? [];
3823
+ s.length > 0 ? this._grpMgr.groupBy(s) : this.clearGroup();
3824
+ return;
3825
+ }
3826
+ this._renderHeader(), this._doRender(...this._visRange());
3827
+ }
3828
+ /**
3829
+ * 컬럼 마스킹 ON/OFF 전환.
3830
+ * enabled=true → 마스킹 적용 (기본 상태)
3831
+ * enabled=false → 컬럼 전체 마스킹 해제 (원문 표시)
3832
+ */
3833
+ setMaskEnabled(e, t) {
3834
+ var n;
3835
+ const s = this._colLayout.getColumnByField(e);
3836
+ s && (t ? (s._maskRevealed = !1, (n = s._maskRevealedRows) == null || n.clear()) : s._maskRevealed = !0, this._doRender(...this._visRange()));
3837
+ }
3838
+ /** 현재 컬럼 마스킹 활성 여부 반환. true=마스킹 중, false=해제됨 */
3839
+ getMaskEnabled(e) {
3840
+ const t = this._colLayout.getColumnByField(e);
3841
+ return t ? t._maskRevealed !== !0 : !1;
3842
+ }
3843
+ _initWorksheets() {
3844
+ const e = this._options.worksheets;
3845
+ this._wsManager = new ze(
3846
+ this._container,
3847
+ (t, s) => {
3848
+ this._data.setData(s.data), this._colLayout = new re(
3849
+ s.columns.length ? s.columns : this._options.columns,
3850
+ this._options.frozenColumns
3851
+ ), this._doRender(...this._visRange()), this._renderHeader();
3852
+ }
3853
+ );
3854
+ for (const t of e)
3855
+ this._wsManager.add(t.name, t.columns ?? this._options.columns, t.data ?? []);
3856
+ }
3857
+ addWorksheet(e, t, s) {
3858
+ this._wsManager || (this._wsManager = new ze(
3859
+ this._container,
3860
+ (n, i) => {
3861
+ this._data.setData(i.data), this._colLayout = new re(
3862
+ i.columns.length ? i.columns : this._options.columns,
3863
+ this._options.frozenColumns
3864
+ ), this._doRender(...this._visRange()), this._renderHeader();
3865
+ }
3866
+ )), this._wsManager.add(e, t ?? this._options.columns, s ?? []);
3867
+ }
3868
+ removeWorksheet(e) {
3869
+ var t;
3870
+ (t = this._wsManager) == null || t.remove(e);
3871
+ }
3872
+ switchWorksheet(e) {
3873
+ var t;
3874
+ (t = this._wsManager) == null || t.switch(e);
3875
+ }
3876
+ renameWorksheet(e, t) {
3877
+ var s;
3878
+ (s = this._wsManager) == null || s.rename(e, t);
3879
+ }
3880
+ getWorksheet(e) {
3881
+ var t;
3882
+ return (t = this._wsManager) == null ? void 0 : t.get(e);
3883
+ }
3884
+ getWorksheetNames() {
3885
+ var e;
3886
+ return ((e = this._wsManager) == null ? void 0 : e.getNames()) ?? [];
3887
+ }
3888
+ exportSheetsExcel(e) {
3889
+ this._exportMgr.exportSheetsExcel(e);
3890
+ }
3891
+ _paginationHeight() {
3892
+ return this._options.pagination ? 38 : 0;
3893
+ }
3894
+ _onResize() {
3895
+ const { width: e, height: t } = this._container.getBoundingClientRect();
3896
+ if (!e) return;
3897
+ const s = t - this._options.headerHeight - this._paginationHeight();
3898
+ this._renderer.updateSize(t - this._paginationHeight(), this._options.headerHeight), this._vs.setViewportHeight(s), this._recalcWidths(e), this._renderHeader(), this._doRender(...this._visRange());
3899
+ }
3900
+ _recalcWidths(e) {
3901
+ this._colWidths = this._colLayout.computeWidths(
3902
+ e - (this._options.stateColumn ? 24 : 0) - (this._options.draggable ? 18 : 0) - (this._options.rowNumber ? 44 : 0) - (this._options.checkColumn ? 36 : 0),
3903
+ this._options.defaultColumnWidth
3904
+ );
3905
+ }
3906
+ // 헤더(컬럼 제목 행)를 다시 그린다
3907
+ _renderHeader() {
3908
+ var e;
3909
+ (e = this._renderer) == null || e.renderHeader(
3910
+ this._colLayout.buildHeaderCells(),
3911
+ this._colLayout.visibleLeaves,
3912
+ this._colWidths,
3913
+ this._sfMgr.sortList,
3914
+ { ...this._options, _activeFilters: this._sfMgr.filters, _frozenCount: this._colLayout.frozenCount }
3915
+ );
3916
+ }
3917
+ _doRender(e, t) {
3918
+ var n;
3919
+ if (!this._renderer || !this._vs) return;
3920
+ const s = this._vs.getVisibleRange();
3921
+ this._renderer.renderBody(
3922
+ e,
3923
+ t,
3924
+ this._data,
3925
+ this._colLayout.visibleLeaves,
3926
+ this._colWidths,
3927
+ this._options,
3928
+ s.offsetY,
3929
+ this._vs.getTotalHeight(),
3930
+ this._rowMgr.selectedRows,
3931
+ this._rowMgr.checkedRows,
3932
+ this._grpMgr.isGroupMode ? this._grpMgr.groupFlatRows : this._grpMgr.isTreeMode ? this._grpMgr.treeFlatRows : null,
3933
+ (i) => this._grpMgr.handleGroupToggle(i),
3934
+ this._grpMgr.isTreeMode ? (i) => this._grpMgr.handleTreeToggle(i) : void 0,
3935
+ { _totalRows: this._data.rowCount, _frozenCount: this._colLayout.frozenCount, _focusCell: this._editMgr.focusCell },
3936
+ this._mergeEngine
3937
+ ), (n = this._options.footer) != null && n.length && this._renderFooterEl();
3938
+ }
3939
+ _handleGroupToggle(e) {
3940
+ this._grpMgr.handleGroupToggle(e);
3941
+ }
3942
+ // 현재 화면에 보이는 행 범위를 반환한다
3943
+ _visRange() {
3944
+ var t;
3945
+ if (this._options.pagination && this._pagination) {
3946
+ const { start: s, end: n } = this._pagination.getRange();
3947
+ return [s, n];
3948
+ }
3949
+ const e = (t = this._vs) == null ? void 0 : t.getVisibleRange();
3950
+ return [(e == null ? void 0 : e.startIndex) ?? 0, Math.min(((e == null ? void 0 : e.endIndex) ?? 30) + this._visCount() + 5, this._data.rowCount - 1)];
3951
+ }
3952
+ _visCount() {
3953
+ const e = this._container.getBoundingClientRect().height;
3954
+ return Math.ceil((e - this._options.headerHeight - this._paginationHeight()) / this._options.rowHeight) + 5;
3955
+ }
3956
+ _handleSortClick(e, t) {
3957
+ this._sfMgr.handleSortClick(e, t);
3958
+ }
3959
+ _isToggleCol(e) {
3960
+ return Z(e);
3961
+ }
3962
+ _handleCellClick(e, t, s) {
3963
+ this._cellEvt.handleCellClick(e, t, s);
3964
+ }
3965
+ _handleCellDblClick(e, t, s) {
3966
+ this._cellEvt.handleCellDblClick(e, t, s);
3967
+ }
3968
+ _handleCellMouseOver(e, t, s) {
3969
+ this._cellEvt.handleCellMouseOver(e, t, s);
3970
+ }
3971
+ _handleCellMouseOut(e, t, s) {
3972
+ this._cellEvt.handleCellMouseOut(e, t, s);
3973
+ }
3974
+ _handleCellMouseDown(e, t, s) {
3975
+ this._cellEvt.handleCellMouseDown(e, t, s);
3976
+ }
3977
+ _handleCellMouseUp(e, t, s) {
3978
+ this._cellEvt.handleCellMouseUp(e, t, s);
3979
+ }
3980
+ _handleCellMouseMove(e, t, s) {
3981
+ this._cellEvt.handleCellMouseMove(e, t, s);
3982
+ }
3983
+ _handleCellKeyEvt(e, t) {
3984
+ this._cellEvt.handleCellKeyEvt(e, t);
3985
+ }
3986
+ _handleRowCheck(e, t) {
3987
+ this._rowMgr.check(e, t), this._doRender(...this._visRange()), this.emit("rowCheck", { rowIndex: e, checked: t, row: this._data.getRowByIndex(e) });
3988
+ }
3989
+ _handleFilterIconClick(e, t) {
3990
+ var n, i;
3991
+ if ((n = this._filterPanel) != null && n.isOpen) {
3992
+ this._filterPanel.close();
3993
+ return;
3994
+ }
3995
+ const s = this._sfMgr.filters[e] ?? [];
3996
+ (i = this._filterPanel) == null || i.open(e, t, s);
3997
+ }
3998
+ _handleAllCheck(e) {
3999
+ this._rowMgr.checkAll(e, this._data.rowCount), this._doRender(...this._visRange()), this.emit("allCheck", { checked: e });
4000
+ }
4001
+ _handleRowDrop(e, t) {
4002
+ var s, n;
4003
+ this._data.moveRow(e, t), this._doRender(...this._visRange()), this.emit("rowDrop", { fromIndex: e, toIndex: t }), (n = (s = this._options).onRowDrop) == null || n.call(s, { fromIndex: e, toIndex: t });
4004
+ }
4005
+ /** 행을 드롭으로 이동할 때 실행된다 */
4006
+ /** ???꾩튂 ?대룞 */
4007
+ reorderRow(e, t) {
4008
+ this._data.moveRow(e, t), this._doRender(...this._visRange());
4009
+ }
4010
+ _handleColResize(e, t) {
4011
+ this._colWidths[e] !== void 0 && (this._colWidths[e] = t), this._doRender(...this._visRange());
4012
+ }
4013
+ _handleKeyDown(e) {
4014
+ this._kbdMgr.handleKeyDown(e);
4015
+ }
4016
+ _setFocusCell(e, t) {
4017
+ this._rowMgr.selectSingle(e), this._editMgr.setFocusCell(e, t);
4018
+ }
4019
+ // 스크린리더에게 텍스트를 읽어준다 (aria-live)
4020
+ _announce(e) {
4021
+ this._liveRegion && (this._liveRegion.textContent = "", setTimeout(() => {
4022
+ this._liveRegion && (this._liveRegion.textContent = e);
4023
+ }, 50));
4024
+ }
4025
+ _bindOptionEvents() {
4026
+ 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);
4027
+ }
4028
+ setData(e) {
4029
+ var s;
4030
+ const t = this._trigMgr.mkCtx("setData", [e]);
4031
+ 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));
4032
+ }
4033
+ getData() {
4034
+ return this._data.getData();
4035
+ }
4036
+ getSourceRows() {
4037
+ return this._data.getOriginalData();
4038
+ }
4039
+ pushData(e) {
4040
+ var n, i;
4041
+ const t = [...this._data.getAllData(), ...e];
4042
+ this._data.setData(t);
4043
+ const s = this._data.rowCount;
4044
+ (n = this._vs) == null || n.setTotalRows(s), (i = this._pagination) == null || i.setTotalRows(s);
4045
+ }
4046
+ prefixData(e) {
4047
+ var n, i;
4048
+ const t = [...e, ...this._data.getAllData()];
4049
+ this._data.setData(t);
4050
+ const s = this._data.rowCount;
4051
+ (n = this._vs) == null || n.setTotalRows(s), (i = this._pagination) == null || i.setTotalRows(s);
4052
+ }
4053
+ clearData() {
4054
+ var e, t;
4055
+ 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", []);
4056
+ }
4057
+ insertRow(e, t = "last") {
4058
+ var o, l, r, a;
4059
+ const s = this._trigMgr.mkCtx("insertRow", [e, t]);
4060
+ if (!this._trigMgr.exec("before:insertRow", s)) return;
4061
+ const n = t === "before" ? 0 : t === "after" ? this._data.rowCount : t;
4062
+ this._data.addRow(e, n);
4063
+ const i = this._data.rowCount;
4064
+ (o = this._vs) == null || o.setTotalRows(i), (l = this._pagination) == null || l.setTotalRows(i), 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: i, item: e }, this._trigMgr.exec("after:insertRow", s);
4065
+ }
4066
+ pushRow(e) {
4067
+ var n, i, o, l;
4068
+ (Array.isArray(e) ? e : [e]).forEach((r) => this._data.addRow(r, "last"));
4069
+ const s = this._data.rowCount;
4070
+ (n = this._vs) == null || n.setTotalRows(s), (i = this._pagination) == null || i.setTotalRows(s), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (l = (o = this._options).onDataChange) == null || l.call(o, this._data.getData());
4071
+ }
4072
+ /** @deprecated 하위호환 alias → pushRow */
4073
+ appendRows(e) {
4074
+ this.pushRow(e);
4075
+ }
4076
+ unshiftRow(e) {
4077
+ var n, i, o, l;
4078
+ (Array.isArray(e) ? e : [e]).forEach((r) => this._data.addRow(r, "first"));
4079
+ const s = this._data.rowCount;
4080
+ (n = this._vs) == null || n.setTotalRows(s), (i = this._pagination) == null || i.setTotalRows(s), this._doRender(...this._visRange()), this.emit("dataChange", this._data.getData()), (l = (o = this._options).onDataChange) == null || l.call(o, this._data.getData());
4081
+ }
4082
+ /** @deprecated 하위호환 alias → unshiftRow */
4083
+ prependRows(e) {
4084
+ this.unshiftRow(e);
4085
+ }
4086
+ deleteRow(e) {
4087
+ var o, l, r, a;
4088
+ const t = this._trigMgr.mkCtx("deleteRow", [e]), s = Array.isArray(e) ? [...e] : [e];
4089
+ if (t.extra = { rows: s.map((c) => this._data.getRowByIndex(c)) }, !this._trigMgr.exec("before:deleteRow", t)) return;
4090
+ const n = s.sort((c, h) => h - c);
4091
+ n.forEach((c) => this._data.removeRow(c));
4092
+ const i = this._data.rowCount;
4093
+ (o = this._vs) == null || o.setTotalRows(i), (l = this._pagination) == null || l.setTotalRows(i), 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: n.length, rowCount: i }, this._trigMgr.exec("after:deleteRow", t);
4094
+ }
4095
+ deleteById(e) {
4096
+ }
4097
+ readCell(e, t) {
4098
+ return this._data.getCellValue(e, t);
4099
+ }
4100
+ getDisplayValue(e, t) {
4101
+ const s = this.readCell(e, t);
4102
+ return s == null ? "" : String(s);
4103
+ }
4104
+ writeCell(e, t, s) {
4105
+ var c, h, u, g;
4106
+ const n = this.readCell(e, t), i = this._trigMgr.mkCtx("writeCell", [e, t, s]);
4107
+ if (i.extra = { oldValue: n, rowIndex: e, field: t }, !this._trigMgr.exec("before:writeCell", i)) return;
4108
+ this._data.updateCell(e, t, s);
4109
+ 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: n, newValue: s, row: o, column: l };
4110
+ 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()), i.result = { rowIndex: e, field: t, oldValue: n, newValue: s }, this._trigMgr.exec("after:writeCell", i);
4111
+ }
4112
+ getRowAt(e) {
4113
+ return this._data.getRowByIndex(e);
4114
+ }
4115
+ getChanges() {
4116
+ return this._data.getChanges();
4117
+ }
4118
+ getEditedRows() {
4119
+ return this._data.getEditedRows();
4120
+ }
4121
+ getChangedRows() {
4122
+ return this._data.getChangedRows();
4123
+ }
4124
+ // ?섏쐞 ?명솚
4125
+ getChangedColumns() {
4126
+ return this._data.getChangedColumns();
4127
+ }
4128
+ getAddedRows() {
4129
+ return this._data.getAddedRows();
4130
+ }
4131
+ getRemovedRows() {
4132
+ return this._data.getRemovedRows();
4133
+ }
4134
+ getOriginalRow(e) {
4135
+ return this._data.getOriginalRow(e);
4136
+ }
4137
+ getRowsWithState(e) {
4138
+ return this._data.getRowsWithState(e);
4139
+ }
4140
+ undo() {
4141
+ }
4142
+ redo() {
4143
+ }
4144
+ clearHistory() {
4145
+ }
4146
+ getColumnDefs() {
4147
+ return this._colLayout.visibleLeaves;
4148
+ }
4149
+ getAllColumnDefs() {
4150
+ return this._colLayout.leaves;
4151
+ }
4152
+ getColumnCount() {
4153
+ return this._colLayout.visibleLeaves.length;
4154
+ }
4155
+ applyColumns(e) {
4156
+ const t = this._trigMgr.mkCtx("applyColumns", [e]);
4157
+ 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));
4158
+ }
4159
+ insertColumn(e, t) {
4160
+ this._colLayout.addColumn(e, t), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4161
+ }
4162
+ deleteColumn(e) {
4163
+ this._colLayout.removeColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4164
+ }
4165
+ _reorderColumn(e, t) {
4166
+ var o, l;
4167
+ const s = this._colLayout.visibleLeaves.map((r) => r);
4168
+ if (e < 0 || t < 0 || e >= s.length || t >= s.length) return;
4169
+ const n = [...this._options.columns], [i] = n.splice(e, 1);
4170
+ n.splice(t, 0, i), this._options.columns = n, this.applyColumns(n), (l = (o = this._options).onColumnReorder) == null || l.call(o, { fromIndex: e, toIndex: t, field: i.field ?? "" });
4171
+ }
4172
+ hideColumn(e) {
4173
+ this._colLayout.hideColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4174
+ }
4175
+ showColumn(e) {
4176
+ this._colLayout.showColumn(e), this._recalcWidths(this._container.getBoundingClientRect().width), this._renderHeader(), this._doRender(...this._visRange());
4177
+ }
4178
+ getColumnIndex(e) {
4179
+ return this._colLayout.getColumnIndex(e);
4180
+ }
4181
+ getFieldAt(e) {
4182
+ var t;
4183
+ return ((t = this._colLayout.getColumnByIndex(e)) == null ? void 0 : t.field) ?? "";
4184
+ }
4185
+ getColValues(e, t = !1) {
4186
+ return this._data.getData().map((s) => s[e]);
4187
+ }
4188
+ getUniqueValues(e, t = !1) {
4189
+ return [...new Set(this.getColValues(e, t))];
4190
+ }
4191
+ setColWidths(e) {
4192
+ }
4193
+ calcColWidths(e = !1) {
4194
+ return [];
4195
+ }
4196
+ getSelections() {
4197
+ return this._rowMgr.getSelections();
4198
+ }
4199
+ getActiveRow() {
4200
+ return this._rowMgr.getActiveRow();
4201
+ }
4202
+ activate(e) {
4203
+ this._rowMgr.activate(e), this._doRender(...this._visRange());
4204
+ }
4205
+ deselect() {
4206
+ this._rowMgr.deselect(), this._doRender(...this._visRange());
4207
+ }
4208
+ getChecked() {
4209
+ return this._rowMgr.getChecked();
4210
+ }
4211
+ getAllChecked() {
4212
+ return this._rowMgr.getAllChecked();
4213
+ }
4214
+ checkById(e) {
4215
+ }
4216
+ addCheckById(e) {
4217
+ }
4218
+ checkByValue(e, t) {
4219
+ this._rowMgr.checkByValue(e, t), this._doRender(...this._visRange());
4220
+ }
4221
+ uncheckById(e) {
4222
+ }
4223
+ uncheckAll() {
4224
+ this._rowMgr.uncheckAll(), this._doRender(...this._visRange());
4225
+ }
4226
+ orderBy(e, t = "asc") {
4227
+ const s = this._trigMgr.mkCtx("orderBy", [e, t]);
4228
+ this._trigMgr.exec("before:orderBy", s) && (this._sfMgr.sort(e, t), s.result = { sortList: this._sfMgr.sortList }, this._trigMgr.exec("after:orderBy", s));
4229
+ }
4230
+ resetOrder() {
4231
+ this._sfMgr.resetSort();
4232
+ }
4233
+ setFilter(e, t) {
4234
+ const s = this._trigMgr.mkCtx("setFilter", [e, t]);
4235
+ 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));
4236
+ }
4237
+ resetFilter(e) {
4238
+ this._sfMgr.resetFilter(e);
4239
+ }
4240
+ getFilterState() {
4241
+ return this._sfMgr.getFilterState();
4242
+ }
4243
+ restoreFilter(e) {
4244
+ this._sfMgr.restoreFilter(e);
4245
+ }
4246
+ _applyFilters() {
4247
+ this._sfMgr.applyFilters();
4248
+ }
4249
+ freeze(e) {
4250
+ this._colLayout.setFrozen(e), this._renderHeader(), this._doRender(...this._visRange());
4251
+ }
4252
+ /** ?섎룞 蹂묓빀: [{row, col, rowSpan?, colSpan?}] */
4253
+ mergeCells(e) {
4254
+ this._mergeEngine.applyMergeCells(e), this._doRender(...this._visRange());
4255
+ }
4256
+ /** 자동 병합: 지정 필드 컬럼에서 연속 같은 값을 rowSpan으로 묶는다 */
4257
+ /** ?먮룞 蹂묓빀: 吏€??field 而щ읆?먯꽌 ?곗냽 媛숈? 媛믪쓣 rowSpan */
4258
+ autoMerge(e) {
4259
+ const t = this._colLayout.visibleLeaves, s = [], n = [];
4260
+ for (const i of e) {
4261
+ const o = t.findIndex((l) => l.field === i);
4262
+ o >= 0 && (s.push(o), n.push(i));
4263
+ }
4264
+ this._mergeEngine.applyAutoMerge(this._data.getData(), s, n), this._doRender(...this._visRange());
4265
+ }
4266
+ /** 蹂묓빀 ?댁젣 */
4267
+ clearMerge() {
4268
+ this._mergeEngine.clear(), this._doRender(...this._visRange());
4269
+ }
4270
+ freezeRows(e) {
4271
+ }
4272
+ groupBy(e) {
4273
+ const t = this._trigMgr.mkCtx("groupBy", [e]);
4274
+ this._trigMgr.exec("before:groupBy", t) && (this._grpMgr.groupBy(e), t.result = { fields: e }, this._trigMgr.exec("after:groupBy", t));
4275
+ }
4276
+ clearGroup() {
4277
+ this._grpMgr.clearGroup();
4278
+ }
4279
+ expandAll() {
4280
+ this._grpMgr.expandAll();
4281
+ }
4282
+ collapseAll() {
4283
+ this._grpMgr.collapseAll();
4284
+ }
4285
+ enableTree() {
4286
+ this._grpMgr.enableTree();
4287
+ }
4288
+ disableTree() {
4289
+ this._grpMgr.disableTree();
4290
+ }
4291
+ expandNodes(e, t = !0) {
4292
+ this._grpMgr.expandNodes(e, t);
4293
+ }
4294
+ expandAllNodes() {
4295
+ this._grpMgr.expandAllNodes();
4296
+ }
4297
+ collapseAllNodes() {
4298
+ this._grpMgr.collapseAllNodes();
4299
+ }
4300
+ addTreeRow(e, t, s) {
4301
+ }
4302
+ exportExcel(e) {
4303
+ this._exportMgr.exportExcel(e);
4304
+ }
4305
+ exportCsv(e) {
4306
+ this._exportMgr.exportCsv(e);
4307
+ }
4308
+ exportJson(e) {
4309
+ this._exportMgr.exportJson(e);
4310
+ }
4311
+ print(e) {
4312
+ this._exportMgr.print(e);
4313
+ }
4314
+ toArray(e = !0) {
4315
+ const t = this._data.getData();
4316
+ if (e) return t;
4317
+ const s = this._colLayout.visibleLeaves;
4318
+ return t.map((n) => s.map((i) => n[i.field]));
4319
+ }
4320
+ jumpToRow(e) {
4321
+ var t;
4322
+ this._rowMgr.selectSingle(e), (t = this._vs) == null || t.scrollToRow(e), this._doRender(...this._visRange());
4323
+ }
4324
+ jumpToCol(e) {
4325
+ }
4326
+ getScrollPos() {
4327
+ var e, t;
4328
+ return { x: ((e = this._renderer) == null ? void 0 : e.bodyWrapper.scrollLeft) ?? 0, y: ((t = this._renderer) == null ? void 0 : t.bodyWrapper.scrollTop) ?? 0 };
4329
+ }
4330
+ setFooter(e) {
4331
+ this._options.footer = e, this._renderFooterEl();
4332
+ }
4333
+ getFooterData() {
4334
+ return this._footerMgr.computeValues();
4335
+ }
4336
+ getFooterValue(e) {
4337
+ var t;
4338
+ return ((t = this._footerMgr.computeValues().find((s) => s._field === e)) == null ? void 0 : t._value) ?? null;
4339
+ }
4340
+ _renderFooterEl() {
4341
+ this._footerMgr.render();
4342
+ }
4343
+ resize(e, t) {
4344
+ e && (this._container.style.width = `${e}px`), t && (this._container.style.height = `${t}px`), this._onResize();
4345
+ }
4346
+ setTheme(e) {
4347
+ this._container.setAttribute("data-og-theme", e);
4348
+ }
4349
+ setThemeVar(e, t) {
4350
+ this._container.style.setProperty(e, t);
4351
+ }
4352
+ addTrigger(e, t) {
4353
+ return this._trigMgr.add(e, t), this;
4354
+ }
4355
+ removeTrigger(e, t) {
4356
+ return this._trigMgr.remove(e, t), this;
4357
+ }
4358
+ clearTriggers(e) {
4359
+ return this._trigMgr.clear(e), this;
4360
+ }
4361
+ _mkCtx(e, t) {
4362
+ return this._trigMgr.mkCtx(e, t);
4363
+ }
4364
+ _trig(e, t) {
4365
+ return this._trigMgr.exec(e, t);
4366
+ }
4367
+ destroy() {
4368
+ var e, t, s, n, i, o, l, r;
4369
+ 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(), (n = this._dnd) == null || n.destroy(), this._cmHandler && this._container.removeEventListener("contextmenu", this._cmHandler), this._cmKbdHandler && this._container.removeEventListener("keydown", this._cmKbdHandler), this._cmHandler = this._cmKbdHandler = null, (i = this._ctxMenu) == null || i.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());
4370
+ }
4371
+ }
4372
+ export {
4373
+ Xt as O,
4374
+ He as b
4375
+ };
4376
+ //# sourceMappingURL=OpenGrid-CfZy3e7Q.js.map