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,46 @@
1
+ import { DataLayer } from './DataLayer.js';
2
+ import { ColumnLayout } from './ColumnLayout.js';
3
+ import { GridRenderer } from './GridRenderer.js';
4
+ import { CellEditor } from './editors/CellEditor.js';
5
+ import { ColumnDef } from './types.js';
6
+
7
+ export interface CellEditDeps<T extends Record<string, any>> {
8
+ data: DataLayer<T>;
9
+ colLayout: ColumnLayout<T>;
10
+ getRenderer: () => GridRenderer | null;
11
+ getContainer: () => HTMLElement;
12
+ getOptions: () => any;
13
+ emit: (event: string, ...args: any[]) => void;
14
+ doRender: () => void;
15
+ announce: (msg: string) => void;
16
+ writeCell: (ri: number, field: string, value: any) => void;
17
+ scrollToRow: (ri: number) => void;
18
+ getVisibleLeaves: () => ColumnDef<T>[];
19
+ }
20
+ export declare class CellEditManager<T extends Record<string, any> = any> {
21
+ private _activeEditor;
22
+ private _editCell;
23
+ private _focusCell;
24
+ private _dragColIdx;
25
+ private _d;
26
+ constructor(deps: CellEditDeps<T>);
27
+ get activeEditor(): CellEditor | null;
28
+ get editCell(): {
29
+ ri: number;
30
+ ci: number;
31
+ } | null;
32
+ get focusCell(): {
33
+ ri: number;
34
+ ci: number;
35
+ } | null;
36
+ get dragColIdx(): number | null;
37
+ set dragColIdx(v: number | null);
38
+ setFocusCell(ri: number, ci: number): void;
39
+ clearFocusCell(): void;
40
+ startEditByKey(rowIndex: number, colIndex: number): void;
41
+ startEdit(rowIndex: number, colIndex: number, _e: MouseEvent): void;
42
+ commitEdit(): void;
43
+ commitEditWithValue(ri: number, ci: number, value: any): void;
44
+ cancelEdit(): void;
45
+ private _finishEdit;
46
+ }
@@ -0,0 +1,28 @@
1
+ import { DataLayer } from './DataLayer.js';
2
+ import { ColumnLayout } from './ColumnLayout.js';
3
+ import { CellEditManager } from './CellEditManager.js';
4
+ import { RowManager } from './RowManager.js';
5
+
6
+ export interface CellEventDeps<T extends Record<string, any>> {
7
+ getData: () => DataLayer<T>;
8
+ getColLayout: () => ColumnLayout<T>;
9
+ getOptions: () => any;
10
+ getEditMgr: () => CellEditManager<T>;
11
+ getRowMgr: () => RowManager<T>;
12
+ emit: (event: string, ...args: any[]) => void;
13
+ writeCell: (ri: number, field: string, value: any) => void;
14
+ doRender: () => void;
15
+ getContainer: () => HTMLElement;
16
+ }
17
+ export declare class CellEventHandler<T extends Record<string, any> = any> {
18
+ private _d;
19
+ constructor(deps: CellEventDeps<T>);
20
+ handleCellClick(rowIndex: number, colIndex: number, e: MouseEvent): void;
21
+ handleCellDblClick(rowIndex: number, colIndex: number, e: MouseEvent): void;
22
+ handleCellMouseOver(ri: number, ci: number, e: MouseEvent): void;
23
+ handleCellMouseOut(ri: number, ci: number, e: MouseEvent): void;
24
+ handleCellMouseDown(ri: number, ci: number, e: MouseEvent): void;
25
+ handleCellMouseUp(ri: number, ci: number, e: MouseEvent): void;
26
+ handleCellMouseMove(ri: number, ci: number, e: MouseEvent): void;
27
+ handleCellKeyEvt(eventName: 'cellKeyDown' | 'cellKeyUp' | 'cellKeyPress', e: KeyboardEvent): void;
28
+ }
@@ -0,0 +1,5 @@
1
+ import { ColumnDef } from './types.js';
2
+
3
+ export declare function isToggleCol<T>(col: ColumnDef<T>): boolean;
4
+ export declare function isSelectCol<T>(col: ColumnDef<T>): boolean;
5
+ export declare function isRadioCol<T>(col: ColumnDef<T>): boolean;
@@ -0,0 +1,41 @@
1
+ import { ColumnDef } from './types.js';
2
+
3
+ export interface FlatColumn<T = any> extends ColumnDef<T> {
4
+ _colIndex: number;
5
+ _depth: number;
6
+ _leaf: boolean;
7
+ _colSpanCount?: number;
8
+ _rowSpanCount?: number;
9
+ }
10
+ export interface HeaderCell {
11
+ column: FlatColumn;
12
+ colIndex: number;
13
+ depth: number;
14
+ colSpan: number;
15
+ rowSpan: number;
16
+ }
17
+ export declare class ColumnLayout<T = any> {
18
+ private _columns;
19
+ private _flatLeaves;
20
+ private _maxDepth;
21
+ private _frozenCount;
22
+ constructor(columns: ColumnDef<T>[], frozenCount?: number);
23
+ private _process;
24
+ get leaves(): FlatColumn<T>[];
25
+ get visibleLeaves(): FlatColumn<T>[];
26
+ get headerDepth(): number;
27
+ get frozenCount(): number;
28
+ setFrozen(count: number): void;
29
+ setColumns(columns: ColumnDef<T>[]): void;
30
+ hideColumn(field: string | string[]): void;
31
+ showColumn(field: string | string[]): void;
32
+ addColumn(colDef: ColumnDef<T>, position?: 'first' | 'last' | number): void;
33
+ removeColumn(field: string): void;
34
+ getColumnByField(field: string): FlatColumn<T> | undefined;
35
+ getColumnByIndex(index: number): FlatColumn<T> | undefined;
36
+ getColumnIndex(field: string): number;
37
+ /** 헤더 렌더링용 셀 계산 */
38
+ buildHeaderCells(): HeaderCell[][];
39
+ /** 각 리프 컬럼의 계산된 너비 배열 반환 */
40
+ computeWidths(totalWidth: number, defaultWidth?: number): number[];
41
+ }
@@ -0,0 +1,33 @@
1
+ import { ContextMenuItem } from './types.js';
2
+
3
+ export type { ContextMenuItem };
4
+ export interface ContextMenuActions {
5
+ onSortAsc: () => void;
6
+ onSortDesc: () => void;
7
+ onFind: () => void;
8
+ onExcel: () => void;
9
+ onCsv: () => void;
10
+ onPrint: () => void;
11
+ }
12
+ export declare const DEFAULT_CONTEXT_ITEMS: ContextMenuItem[];
13
+ export declare class ContextMenuManager {
14
+ private readonly _anchor;
15
+ private readonly _actions;
16
+ private _el;
17
+ private _docClick;
18
+ private _docKey;
19
+ private _docScroll;
20
+ private _docMouseMove;
21
+ private _focusIdx;
22
+ /**
23
+ * @param _anchor 그리드 컨테이너 엘리먼트 — CSS 변수 상속 기준점
24
+ * @param _actions 기본 액션 핸들러 (OpenGrid에서 주입)
25
+ */
26
+ constructor(_anchor: HTMLElement, _actions: ContextMenuActions);
27
+ open(e: MouseEvent, customItems?: ContextMenuItem[]): void;
28
+ close(): void;
29
+ destroy(): void;
30
+ private _position;
31
+ private _moveFocus;
32
+ private _runAction;
33
+ }
@@ -0,0 +1,65 @@
1
+ import { SortItem, FilterItem } from './types.js';
2
+
3
+ type RowState = 'added' | 'edited' | 'removed' | 'none';
4
+ export declare class DataLayer<T extends Record<string, any> = any> {
5
+ private _data;
6
+ private _original;
7
+ private _meta;
8
+ private _idField;
9
+ private _displayIndexes;
10
+ private _idMap;
11
+ private _findQuery;
12
+ private _findFields;
13
+ constructor(idField?: string);
14
+ setData(data: T[]): void;
15
+ getData(): T[];
16
+ getOriginalData(): T[];
17
+ getAllData(): T[];
18
+ clearData(): void;
19
+ get rowCount(): number;
20
+ get totalRowCount(): number;
21
+ addRow(item: Partial<T>, position?: 'first' | 'last' | number): void;
22
+ removeRow(rowIndex: number): T | undefined;
23
+ moveRow(fromDisplayIdx: number, toDisplayIdx: number): void;
24
+ updateCell(rowIndex: number, field: string, value: any): boolean;
25
+ getRowByIndex(rowIndex: number): T | undefined;
26
+ getCellValue(rowIndex: number, field: string): any;
27
+ /** 수정된 행만 반환 (추가/삭제 제외) */
28
+ getEditedRows(): T[];
29
+ /** 수정된 행만 반환 (하위 호환용 — 신규 코드는 getEditedRows() 사용) */
30
+ getChangedRows(): T[];
31
+ getAddedRows(): T[];
32
+ getRemovedRows(): T[];
33
+ /**
34
+ * 추가/수정/삭제 모든 변경사항을 한 번에 반환.
35
+ * edited 행에는 _changedFields 배열도 포함.
36
+ */
37
+ getChanges(): {
38
+ added: T[];
39
+ edited: T[];
40
+ removed: T[];
41
+ };
42
+ /**
43
+ * 수정된 컬럼 정보 반환 — 각 edited 행에 대해 { row, fields, diff } 반환.
44
+ * diff: { field, oldValue, newValue }[]
45
+ */
46
+ getChangedColumns(): Array<{
47
+ row: T;
48
+ fields: string[];
49
+ diff: Array<{
50
+ field: string;
51
+ oldValue: any;
52
+ newValue: any;
53
+ }>;
54
+ }>;
55
+ /** rowIndex 행의 원본(수정 전) 데이터 반환. 추가된 행은 undefined. */
56
+ getOriginalRow(rowIndex: number): T | undefined;
57
+ getRowsWithState(stateField: string): T[];
58
+ getRowState(rowIndex: number): RowState;
59
+ applySort(sortList: SortItem[]): void;
60
+ applyFilter(filters: Record<string, FilterItem[]>): void;
61
+ /** F3: 찾기 바 전체 컬럼 OR 검색 설정 */
62
+ setFindFilter(query: string, fields: string[]): void;
63
+ private _rebuildIdMap;
64
+ }
65
+ export {};
@@ -0,0 +1,11 @@
1
+ type Handler = (...args: any[]) => any;
2
+ export declare class EventEmitter {
3
+ private listeners;
4
+ on(event: string, handler: Handler): this;
5
+ once(event: string, handler: Handler): this;
6
+ off(event: string, handler?: Handler): this;
7
+ emit(event: string, ...args: any[]): boolean;
8
+ removeAllListeners(event?: string): this;
9
+ listenerCount(event: string): number;
10
+ }
11
+ export {};
@@ -0,0 +1,28 @@
1
+ import { ColumnLayout } from './ColumnLayout.js';
2
+ import { WorksheetManager } from './WorksheetManager.js';
3
+ import { ExportOptions } from './types.js';
4
+
5
+ export interface ExportDeps<T extends Record<string, any>> {
6
+ getData: () => T[];
7
+ getColLayout: () => ColumnLayout<T>;
8
+ getColWidths: () => number[];
9
+ getOptions: () => any;
10
+ getContainer: () => HTMLElement;
11
+ getMaskEnabled: (field: string) => boolean;
12
+ getWsManager: () => WorksheetManager<T> | null;
13
+ }
14
+ export declare class ExportManager<T extends Record<string, any> = any> {
15
+ private _d;
16
+ constructor(deps: ExportDeps<T>);
17
+ private _readCssVar;
18
+ private _hexToXlsxRgb;
19
+ exportExcel(options?: ExportOptions | string): void;
20
+ exportCsv(options?: ExportOptions | string): void;
21
+ exportJson(options?: ExportOptions | string): void;
22
+ print(options?: {
23
+ title?: string;
24
+ excludeFields?: string[];
25
+ footerText?: string;
26
+ }): void;
27
+ exportSheetsExcel(filename?: string): void;
28
+ }
@@ -0,0 +1,20 @@
1
+ import { FilterItem } from './types.js';
2
+
3
+ export type FilterApplyFn = (field: string, items: FilterItem[]) => void;
4
+ export type FilterClearFn = (field: string) => void;
5
+ /**
6
+ * 컬럼 헤더 필터 드롭다운 패널.
7
+ * 단일 인스턴스를 재사용(열릴 때 위치 재계산).
8
+ */
9
+ export declare class FilterPanel {
10
+ private _el;
11
+ private _field;
12
+ private _onApply;
13
+ private _onClear;
14
+ private _outsideHandler;
15
+ constructor(container: HTMLElement, onApply: FilterApplyFn, onClear: FilterClearFn);
16
+ open(field: string, anchorEl: HTMLElement, currentFilters: FilterItem[]): void;
17
+ close(): void;
18
+ get isOpen(): boolean;
19
+ destroy(): void;
20
+ }
@@ -0,0 +1,96 @@
1
+ import { FilterItem } from './types.js';
2
+
3
+ export interface FilterSelectOption {
4
+ value: string;
5
+ text: string;
6
+ }
7
+ /**
8
+ * 캐스케이딩 필터 셀렉트 컬럼 정의.
9
+ *
10
+ * ### 데이터 공급 방식 (택 1)
11
+ *
12
+ * **A. JSON 배열 바인딩** (권장)
13
+ * ```ts
14
+ * {
15
+ * field: 'brand',
16
+ * label: '브랜드',
17
+ * data: brandList, // any[] ← JSON 배열
18
+ * valueKey: 'brandCode', // 필터·선택값으로 사용할 키
19
+ * textKey: 'brandName', // 화면에 표시할 텍스트 키
20
+ * filterKey: 'brand', // 그리드 행 데이터의 필터 기준 키 (기본: field)
21
+ * dependsOn: 'category', // 부모 컬럼 field
22
+ * dependsOnKey: 'catCode', // 자식 data[]에서 부모값과 매칭할 키
23
+ * }
24
+ * ```
25
+ *
26
+ * **B. 정적 옵션 배열**
27
+ * ```ts
28
+ * { field: 'status', options: [{ value: 'Y', text: '활성' }] }
29
+ * ```
30
+ */
31
+ export interface FilterSelectColumn {
32
+ /** 캐스케이딩 식별자 / 기본 필터 키 */
33
+ field: string;
34
+ /** 화면 표시 라벨 */
35
+ label: string;
36
+ /** 바인딩할 JSON 배열 */
37
+ data?: any[];
38
+ /** data[]에서 option value로 사용할 키 */
39
+ valueKey?: string;
40
+ /** data[]에서 화면 표시 text로 사용할 키 (미지정 시 valueKey 사용) */
41
+ textKey?: string;
42
+ /**
43
+ * 그리드 행 데이터에서 실제 필터링할 키.
44
+ * 미지정 시 `field` 값 그대로 사용.
45
+ *
46
+ * @example
47
+ * // 그리드 row.category === selectedValue 로 필터링
48
+ * filterKey: 'category'
49
+ */
50
+ filterKey?: string;
51
+ options?: FilterSelectOption[];
52
+ /** 부모 컬럼의 field 명 */
53
+ dependsOn?: string;
54
+ /**
55
+ * 자식 data[]에서 부모 선택값과 비교할 키.
56
+ *
57
+ * @example
58
+ * // brandList.filter(b => b.catCode === parentSelectedValue)
59
+ * dependsOnKey: 'catCode'
60
+ */
61
+ dependsOnKey?: string;
62
+ }
63
+ export interface FilterSelectConfig {
64
+ columns: FilterSelectColumn[];
65
+ /** fieldset 제목 (기본: '필터') */
66
+ legend?: string;
67
+ }
68
+ type FilterFn = (field: string, items: FilterItem[]) => void;
69
+ type ResetFn = (field?: string) => void;
70
+ export declare class FilterSelectPanel {
71
+ private _el;
72
+ private _selects;
73
+ /** 현재 선택 상태 { field → selectedValue } */
74
+ private _selected;
75
+ private _config;
76
+ private _onFilter;
77
+ private _onReset;
78
+ constructor(container: HTMLElement, config: FilterSelectConfig, onFilter: FilterFn, onReset: ResetFn, gridId?: string);
79
+ /**
80
+ * 컬럼의 옵션 목록을 계산한다.
81
+ *
82
+ * @param col 대상 컬럼 정의
83
+ * @param parentValue 부모 선택값 (캐스케이딩 필터에 사용)
84
+ */
85
+ private _resolve;
86
+ private _fill;
87
+ private _onChange;
88
+ /**
89
+ * 부모 컬럼 변경 후 자식 컬럼 옵션을 재계산한다 (재귀).
90
+ */
91
+ private _cascade;
92
+ private _reset;
93
+ reset(): void;
94
+ destroy(): void;
95
+ }
96
+ export {};
@@ -0,0 +1,26 @@
1
+ import { ColumnLayout } from './ColumnLayout.js';
2
+ import { DataLayer } from './DataLayer.js';
3
+ import { Pagination } from './Pagination.js';
4
+ import { VirtualScroll } from './VirtualScroll.js';
5
+
6
+ export interface FindBarDeps<T extends Record<string, any>> {
7
+ getColLayout: () => ColumnLayout<T>;
8
+ getData: () => DataLayer<T>;
9
+ getFilters: () => Record<string, any[]>;
10
+ getVs: () => VirtualScroll | null;
11
+ getPagination: () => Pagination | null;
12
+ doRender: () => void;
13
+ }
14
+ export declare class FindBarManager<T extends Record<string, any> = any> {
15
+ private _bar;
16
+ private _input;
17
+ private _count;
18
+ private _filter;
19
+ private _d;
20
+ constructor(deps: FindBarDeps<T>);
21
+ get findFilter(): string;
22
+ init(container: HTMLElement): void;
23
+ open(): void;
24
+ close(): void;
25
+ private _apply;
26
+ }
@@ -0,0 +1,16 @@
1
+ import { ColumnLayout } from './ColumnLayout.js';
2
+
3
+ export interface FooterDeps<T extends Record<string, any>> {
4
+ getData: () => T[];
5
+ getColLayout: () => ColumnLayout<T>;
6
+ getColWidths: () => number[];
7
+ getOptions: () => any;
8
+ getContainer: () => HTMLElement;
9
+ }
10
+ export declare class FooterManager<T extends Record<string, any> = any> {
11
+ private _d;
12
+ constructor(deps: FooterDeps<T>);
13
+ fmtNum(value: number, fmt?: string): string;
14
+ computeValues(): any[];
15
+ render(): void;
16
+ }
@@ -0,0 +1,10 @@
1
+ import { OGDecimal, OGDecimalLike } from './OGDecimal.js';
2
+
3
+ export type FormulaContext = Record<string, OGDecimalLike>;
4
+ /**
5
+ * 문자열 수식을 평가해 OGDecimal 결과를 반환한다.
6
+ * @param expr - 수식 문자열 (예: "[price] * [qty] * 0.035")
7
+ * @param ctx - 필드값 컨텍스트 (행 데이터)
8
+ * @param divisionPrecision - 나눗셈 소수점 자리수 (기본 30)
9
+ */
10
+ export declare function evaluateFormula(expr: string, ctx: FormulaContext, divisionPrecision?: number): OGDecimal;
@@ -0,0 +1,42 @@
1
+ import { DataLayer } from './DataLayer.js';
2
+ import { RowDragDrop } from './RowDragDrop.js';
3
+ import { MergeEngine } from './MergeEngine.js';
4
+ import { ColumnDef, SortItem } from './types.js';
5
+
6
+ export interface RendererCallbacks {
7
+ onHeaderClick: (field: string, shiftKey: boolean) => void;
8
+ onCellClick: (ri: number, ci: number, e: MouseEvent) => void;
9
+ onCellDblClick: (ri: number, ci: number, e: MouseEvent) => void;
10
+ onCellMouseOver: (ri: number, ci: number, e: MouseEvent) => void;
11
+ onCellMouseOut: (ri: number, ci: number, e: MouseEvent) => void;
12
+ onCellMouseDown: (ri: number, ci: number, e: MouseEvent) => void;
13
+ onCellMouseUp: (ri: number, ci: number, e: MouseEvent) => void;
14
+ onCellMouseMove: (ri: number, ci: number, e: MouseEvent) => void;
15
+ onRowCheck: (ri: number, checked: boolean) => void;
16
+ onAllCheck: (checked: boolean) => void;
17
+ onColResize: (colIndex: number, newWidth: number) => void;
18
+ onFilterIconClick: (field: string, anchorEl: HTMLElement) => void;
19
+ getDndManager: () => RowDragDrop | null;
20
+ onColDragStart: (colIndex: number) => void;
21
+ onColDrop: (toIndex: number) => void;
22
+ getColDragIdx: () => number | null;
23
+ }
24
+ export declare class GridRenderer {
25
+ private _root;
26
+ private _header;
27
+ private _bodyWrap;
28
+ private _body;
29
+ private _opts;
30
+ private _cbs;
31
+ private _cellMap;
32
+ get bodyWrapper(): HTMLElement;
33
+ constructor(root: HTMLElement, opts: any, cbs: RendererCallbacks);
34
+ updateSize(totalHeight: number, headerHeight: number): void;
35
+ renderHeader(headerRows: any[][], leaves: ColumnDef[], widths: number[], sortList: SortItem[], opts: any): void;
36
+ renderBody(startIndex: number, endIndex: number, data: DataLayer<any>, leaves: ColumnDef[], widths: number[], opts: any, offsetY: number, totalHeight: number, selectedRows: Set<number>, checkedRows: Set<number>, groupFlatRows?: Array<any> | null, onGroupToggle?: (key: string) => void, onTreeToggle?: (nodeId: any) => void, extraOpts?: Record<string, any>, mergeEngine?: MergeEngine): void;
37
+ getCellEl(rowIndex: number, colIndex: number): HTMLElement | undefined;
38
+ destroy(): void;
39
+ }
40
+ export declare function _el(tag: string, className?: string): HTMLElement;
41
+ export declare function _style(el: HTMLElement, styles: Partial<CSSStyleDeclaration>): void;
42
+ export declare function _downloadText(content: string, filename: string, mime?: string): void;
@@ -0,0 +1,47 @@
1
+ import { SummaryOp } from './types.js';
2
+
3
+ export interface GroupRow<T = any> {
4
+ _isGroup: true;
5
+ _groupField: string;
6
+ _groupValue: any;
7
+ _groupLabel: string;
8
+ _depth: number;
9
+ _expanded: boolean;
10
+ _childCount: number;
11
+ _summary: Record<string, any>;
12
+ _summaryFmt: Record<string, string>;
13
+ _states: {
14
+ added: number;
15
+ edited: number;
16
+ removed: number;
17
+ };
18
+ children: Array<GroupRow<T> | T>;
19
+ }
20
+ export type GroupItem<T> = GroupRow<T> | T;
21
+ export interface SummaryDef {
22
+ field: string;
23
+ op: SummaryOp;
24
+ label?: string;
25
+ format?: string;
26
+ }
27
+ declare function _isGroup<T>(item: any): item is GroupRow<T>;
28
+ /** flat 데이터를 fields 기준으로 계층 그룹핑 */
29
+ export declare function buildGroups<T extends Record<string, any>>(data: T[], fields: string[], summaryDefs?: SummaryDef[], expandedKeys?: Set<string>, getRowState?: (row: T) => string): GroupRow<T>[];
30
+ /**
31
+ * 숫자 포맷팅 (GroupEngine 내부 + 외부 공용)
32
+ * '#,##0' → 천단위 콤마, 정수
33
+ * '#,##0.00' → 천단위 콤마, 소수 2자리
34
+ * '0.00' → 소수 2자리 (콤마 없음)
35
+ * '2' → 소수 2자리 (하위 호환)
36
+ */
37
+ export declare function _fmtNum(value: number, fmt?: string): string;
38
+ /**
39
+ * 그룹 트리를 화면에 표시할 flat 행 배열로 변환.
40
+ * 접힌 그룹(expanded=false)의 자식은 포함하지 않음.
41
+ */
42
+ export declare function flattenGroups<T>(groups: GroupRow<T>[]): Array<GroupRow<T> | T>;
43
+ /** 특정 그룹 키의 펼침 상태를 토글 */
44
+ export declare function toggleGroup<T>(groups: GroupRow<T>[], groupKey: string, expandedKeys: Set<string>): void;
45
+ /** 모든 그룹 키 수집 */
46
+ export declare function collectAllKeys<T>(groups: GroupRow<T>[], parentKey?: string): string[];
47
+ export { _isGroup };
@@ -0,0 +1,43 @@
1
+ import { DataLayer } from './DataLayer.js';
2
+ import { VirtualScroll } from './VirtualScroll.js';
3
+ import { GroupRow } from './GroupEngine.js';
4
+ import { TreeNode } from './TreeEngine.js';
5
+
6
+ export interface GroupTreeDeps<T extends Record<string, any>> {
7
+ getData: () => T[];
8
+ getDataLayer: () => DataLayer<T>;
9
+ getOptions: () => any;
10
+ getVs: () => VirtualScroll | null;
11
+ doRenderFull: (totalRows: number) => void;
12
+ doRender: () => void;
13
+ }
14
+ export declare class GroupTreeManager<T extends Record<string, any> = any> {
15
+ private _groupFields;
16
+ private _groupExpandedKeys;
17
+ private _groupFlatRows;
18
+ private _isGroupMode;
19
+ private _treeRoots;
20
+ private _treeFlatRows;
21
+ private _treeExpandedKeys;
22
+ private _isTreeMode;
23
+ private _d;
24
+ constructor(deps: GroupTreeDeps<T>);
25
+ get isGroupMode(): boolean;
26
+ get isTreeMode(): boolean;
27
+ get groupFlatRows(): Array<GroupRow<T> | T>;
28
+ get treeFlatRows(): TreeNode<T>[];
29
+ groupBy(fields: string[]): void;
30
+ clearGroup(): void;
31
+ expandAll(): void;
32
+ collapseAll(): void;
33
+ handleGroupToggle(groupKey: string): void;
34
+ rebuildGroups(): void;
35
+ enableTree(): void;
36
+ disableTree(): void;
37
+ expandNodes(ids: any | any[], open?: boolean): void;
38
+ expandAllNodes(): void;
39
+ collapseAllNodes(): void;
40
+ handleTreeToggle(nodeId: any): void;
41
+ rebuildTree(): void;
42
+ private _getSummaryDefs;
43
+ }
@@ -0,0 +1,26 @@
1
+ import { DataLayer } from './DataLayer.js';
2
+ import { ColumnLayout } from './ColumnLayout.js';
3
+ import { CellEditManager } from './CellEditManager.js';
4
+ import { RowManager } from './RowManager.js';
5
+
6
+ export interface KeyboardDeps<T extends Record<string, any>> {
7
+ getEditMgr: () => CellEditManager<T>;
8
+ getRowMgr: () => RowManager<T>;
9
+ getData: () => DataLayer<T>;
10
+ getColLayout: () => ColumnLayout<T>;
11
+ getOptions: () => any;
12
+ setFocusCell: (ri: number, ci: number) => void;
13
+ handleRowDrop: (from: number, to: number) => void;
14
+ doRender: () => void;
15
+ announce: (msg: string) => void;
16
+ emit: (event: string, ...args: any[]) => void;
17
+ visRange: () => [number, number];
18
+ handleCellKeyEvt: (eventName: 'cellKeyDown' | 'cellKeyUp' | 'cellKeyPress', e: KeyboardEvent) => void;
19
+ }
20
+ export declare class KeyboardManager<T extends Record<string, any> = any> {
21
+ private _d;
22
+ constructor(deps: KeyboardDeps<T>);
23
+ handleKeyDown(e: KeyboardEvent): void;
24
+ private _copyToClipboard;
25
+ private _pasteFromClipboard;
26
+ }
@@ -0,0 +1,25 @@
1
+ /** 지원 마스킹 타입 */
2
+ export type MaskType = 'ssn' | 'phone' | 'mobile' | 'email' | 'credit' | 'account' | 'password' | 'name' | 'ip' | 'partial';
3
+ /** 마스킹 상세 옵션 */
4
+ export interface MaskDef {
5
+ type: MaskType;
6
+ /** 마스킹 치환 문자 (기본: '*') */
7
+ char?: string;
8
+ /** partial/account: 앞 N자리 표시 */
9
+ visiblePrefix?: number;
10
+ /** partial/account: 뒤 N자리 표시 */
11
+ visibleSuffix?: number;
12
+ }
13
+ /**
14
+ * 원본 값에 마스킹을 적용해 표시용 문자열을 반환.
15
+ *
16
+ * @param value 원본 값 (null/undefined → 빈 문자열 그대로 반환)
17
+ * @param maskDef 마스킹 타입 또는 상세 옵션
18
+ * @returns 마스킹된 문자열
19
+ *
20
+ * @example
21
+ * applyMask('930101-1234567', 'ssn') // '930101-1******'
22
+ * applyMask('01012345678', 'phone') // '010-****-5678'
23
+ * applyMask('hong@test.com', 'email') // 'ho***@test.com'
24
+ */
25
+ export declare function applyMask(value: string, maskDef: MaskType | MaskDef): string;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 소수점 precision 자리로 반올림 (epsilon round).
3
+ * 0.1+0.2+... 누적 오차를 최종 표시 단계에서 제거한다.
4
+ */
5
+ export declare function round(val: number, precision?: number): number;
6
+ /**
7
+ * Kahan compensated summation — 대량 합산 시 부동소수점 오차 최소화.
8
+ * 시간복잡도 O(n), 공간 O(1). 빈 배열 → 0 반환.
9
+ */
10
+ export declare function kahanSum(arr: number[]): number;
11
+ /**
12
+ * 안전 사칙연산 — 두 수의 곱셈 스케일링으로 소수점 오차 방지.
13
+ */
14
+ export declare function safeAdd(a: number, b: number, precision?: number): number;
15
+ export declare function safeSub(a: number, b: number, precision?: number): number;
16
+ export declare function safeMul(a: number, b: number, precision?: number): number;
17
+ export declare function safeDiv(a: number, b: number, precision?: number): number;
18
+ /**
19
+ * Kahan 합산 후 precision 반올림.
20
+ * SUM/AVG footer 계산에 사용.
21
+ */
22
+ export declare function kahanSumRounded(arr: number[], precision?: number): number;
23
+ /**
24
+ * Kahan AVG — 합산 후 count로 나누기.
25
+ */
26
+ export declare function kahanAvg(arr: number[], precision?: number): number;