open-grid 1.0.8 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/THIRD_PARTY_LICENSES.txt +43 -0
  3. package/dist/OpenGrid-LcZ5iixx.cjs +97 -0
  4. package/dist/OpenGrid-yg4mw6Ge.js +9505 -0
  5. package/dist/open-grid-base.css +66 -5
  6. package/dist/open-grid-react.cjs +1 -1
  7. package/dist/open-grid-react.js +1 -1
  8. package/dist/open-grid-skins.css +111 -0
  9. package/dist/open-grid-themes.css +96 -1
  10. package/dist/open-grid-vue.cjs +1 -1
  11. package/dist/open-grid-vue.js +1 -1
  12. package/dist/open-grid.cjs +3 -3
  13. package/dist/open-grid.js +129 -119
  14. package/dist/types/core/AppearanceResolver.d.ts +100 -0
  15. package/dist/types/core/CellEditManager.d.ts +4 -0
  16. package/dist/types/core/CellEventHandler.d.ts +6 -0
  17. package/dist/types/core/ChartManager.d.ts +58 -0
  18. package/dist/types/core/CrossGridController.d.ts +70 -0
  19. package/dist/types/core/DataLayer.d.ts +17 -0
  20. package/dist/types/core/DetailManager.d.ts +72 -0
  21. package/dist/types/core/ExtensionPointRegistry.d.ts +92 -0
  22. package/dist/types/core/FlatRowModel.d.ts +56 -0
  23. package/dist/types/core/FormulaController.d.ts +79 -0
  24. package/dist/types/core/GridComposer.d.ts +137 -0
  25. package/dist/types/core/GridRenderer.d.ts +73 -4
  26. package/dist/types/core/GroupTreeManager.d.ts +13 -0
  27. package/dist/types/core/IconRegistry.d.ts +55 -0
  28. package/dist/types/core/KeyboardManager.d.ts +19 -0
  29. package/dist/types/core/MutationService.d.ts +126 -0
  30. package/dist/types/core/OpenGrid.d.ts +167 -22
  31. package/dist/types/core/OrgChart.d.ts +2 -0
  32. package/dist/types/core/RangeSelectionManager.d.ts +95 -0
  33. package/dist/types/core/RenderController.d.ts +65 -0
  34. package/dist/types/core/SkinRegistry.d.ts +53 -0
  35. package/dist/types/core/SortFilterManager.d.ts +2 -0
  36. package/dist/types/core/chart/CanvasAdapter.d.ts +52 -0
  37. package/dist/types/core/chart/DataExtractor.d.ts +49 -0
  38. package/dist/types/core/chart/a11y.d.ts +21 -0
  39. package/dist/types/core/chart/downsample.d.ts +25 -0
  40. package/dist/types/core/chart/hittest.d.ts +20 -0
  41. package/dist/types/core/chart/palette.d.ts +56 -0
  42. package/dist/types/core/chart/scales.d.ts +24 -0
  43. package/dist/types/core/chart/types.d.ts +181 -0
  44. package/dist/types/core/detail/DetailGlyph.d.ts +48 -0
  45. package/dist/types/core/detail/DetailSplice.d.ts +67 -0
  46. package/dist/types/core/detail/DetailState.d.ts +67 -0
  47. package/dist/types/core/detail/SubgridCache.d.ts +73 -0
  48. package/dist/types/core/detail/index.d.ts +14 -0
  49. package/dist/types/core/editors/CellEditor.d.ts +17 -1
  50. package/dist/types/core/formula/FormulaEvaluator.d.ts +15 -0
  51. package/dist/types/core/formula/FormulaGraph.d.ts +43 -0
  52. package/dist/types/core/formula/FormulaParser.d.ts +6 -0
  53. package/dist/types/core/formula/FormulaStore.d.ts +17 -0
  54. package/dist/types/core/formula/RecalcCoordinator.d.ts +85 -0
  55. package/dist/types/core/formula/normalizeRefs.d.ts +15 -0
  56. package/dist/types/core/formula/numericLiteral.d.ts +7 -0
  57. package/dist/types/core/formula/serializeFormula.d.ts +6 -0
  58. package/dist/types/core/formula/types.d.ts +104 -0
  59. package/dist/types/core/icons/bootstrap-icons.d.ts +9 -0
  60. package/dist/types/core/range/ClipboardCodec.d.ts +30 -0
  61. package/dist/types/core/range/FillEngine.d.ts +63 -0
  62. package/dist/types/core/range/RangeModel.d.ts +53 -0
  63. package/dist/types/core/range/RangeQuery.d.ts +16 -0
  64. package/dist/types/core/range/types.d.ts +47 -0
  65. package/dist/types/core/renderers/CellRenderer.d.ts +40 -2
  66. package/dist/types/core/types.d.ts +285 -3
  67. package/dist/types/index.d.ts +6 -1
  68. package/package.json +1 -1
  69. package/dist/OpenGrid-CZRcxruq.cjs +0 -90
  70. package/dist/OpenGrid-Cjv7Os5a.js +0 -4871
@@ -0,0 +1,30 @@
1
+ import { CellRange, FlatRowRefLike } from './types.js';
2
+ export interface ClipboardQueryContext {
3
+ fieldAt(ci: number): string | undefined;
4
+ getCellValue(ri: number, field: string): any;
5
+ /** override 데모 정합: 있으면 표시값 우선(§5.1 주석) */
6
+ getDisplayText?(ri: number, field: string): string;
7
+ }
8
+ /** R행×C열 범위 → TSV(행마다 \t조인, 행간 \n) — 엑셀 왕복 호환(UR-4 AC). */
9
+ export declare function rangeToTSV(rect: CellRange, ctx: ClipboardQueryContext): string;
10
+ /** TSV 문자열 → 2D 블록(행×열 문자열 배열). 빈 문자열은 1×1 빈 블록. */
11
+ export declare function parseTSV(text: string): string[][];
12
+ export interface PastePlanContext {
13
+ resolveFlatRow(ri: number): FlatRowRefLike;
14
+ fieldAt(ci: number): string | undefined;
15
+ /** 기본 true(잠금 없음) */
16
+ isEditable?(rowId: string, field: string): boolean;
17
+ }
18
+ export interface PastePlanItem {
19
+ rowIndex: number;
20
+ field: string;
21
+ action: 'value' | 'skip';
22
+ value?: any;
23
+ reason?: string;
24
+ }
25
+ /**
26
+ * 붙여넣기 소스 블록(2D) + 타깃 range → 플랜.
27
+ * 소스가 타깃보다 작으면 타일 반복, 크면(또는 같으면) 블록 그대로 전개(타깃 크기 무시) — 엑셀 규칙(FR-4 AC).
28
+ * `r % blockRows`/`c % blockCols` 단일 공식으로 두 경우 모두 성립(작을 때=주기 반복, 클 때=outRows=blockRows라 항상 r 자신).
29
+ */
30
+ export declare function buildPastePlan(block: string[][], target: CellRange, ctx: PastePlanContext): PastePlanItem[];
@@ -0,0 +1,63 @@
1
+ import { OGDecimal } from '../OGDecimal.js';
2
+ import { CellRange, FillAxis, FillMode, FlatRowRefLike } from './types.js';
3
+ export interface DetectSeriesResult {
4
+ kind: 'copy' | 'arith' | 'text-suffix';
5
+ /** 자연순서(위→아래 / 왼→오) diff. arith/text-suffix에만 존재 */
6
+ step?: OGDecimal;
7
+ /** 자연순서로 파싱된 수치값(arith) 또는 접미 숫자부(text-suffix) */
8
+ values?: OGDecimal[];
9
+ /** text-suffix의 공통 접두문자열 */
10
+ prefix?: string;
11
+ }
12
+ /**
13
+ * 소스 라인(주축과 직교하는 한 행 또는 한 열의 값 배열, 자연순서=위→아래/왼→오) → 감지 결과.
14
+ * 경계 AC(REQ-24): [1,2,4]→copy, [5]→copy, ["a","b"]→copy, ["Q1","Q2"]→arith 아님 text-suffix(step=1).
15
+ */
16
+ export declare function detectSeries(sourceLine: any[]): DetectSeriesResult;
17
+ /**
18
+ * 감지 결과 + 자연순서 소스라인으로 target 거리 d(1..N, 소스에 가장 가까운 셀=1)의 값을 외삽.
19
+ * 방향 부호(§3.4.1 "위/왼쪽 채우면 step 부호 반전")는 axis에 따라 base/부호를 선택해 처리한다.
20
+ */
21
+ export declare function extrapolateValue(result: DetectSeriesResult, sourceLine: any[], axis: FillAxis, d: number): any;
22
+ export interface FillPlanItem {
23
+ rowIndex: number;
24
+ field: string;
25
+ action: 'value' | 'setFormula' | 'skip';
26
+ value?: any;
27
+ formula?: string;
28
+ reason?: string;
29
+ }
30
+ export interface FillPlanResult {
31
+ items: FillPlanItem[];
32
+ /** C3.2 보존된 수식 셀 수(announce용) */
33
+ skippedFormula: number;
34
+ }
35
+ export interface FillPlanContext {
36
+ resolveFlatRow(ri: number): FlatRowRefLike;
37
+ fieldAt(ci: number): string | undefined;
38
+ getCellValue(ri: number, field: string): any;
39
+ /** 기본 true(잠금 없음) */
40
+ isEditable?(rowId: string, field: string): boolean;
41
+ /** 기본 false(수식 없음) */
42
+ hasCellFormula?(rowId: string, field: string): boolean;
43
+ /** C3.1: 상대 ref 오프셋 수식 생성(F3 제공) */
44
+ offsetFormula?(rowId: string, field: string, dRow: number, dCol: number): string;
45
+ /** rangeSelection.fillOverwriteFormula(C3.2 opt-in) */
46
+ overwriteFormula?: boolean;
47
+ /** Ctrl-강제-copy: 수식 원문 복제(오프셋 없음) */
48
+ forceCopyFormula?: boolean;
49
+ }
50
+ /**
51
+ * 소스 rect → 타깃 rect 채우기 플랜(§3.5). 주축과 직교하는 각 라인(행 또는 열) 별로 독립 처리(§3.4.1).
52
+ * non-data 행(kind!=='data')은 항상 skip(C0.3/CON-5). mode==='series'가 detectSeries로 'copy'에
53
+ * 귀결되면(경계 케이스) 그대로 copy 타일 반복으로 처리된다(설계가 의도한 동작).
54
+ */
55
+ export declare function buildFillPlan(source: CellRange, target: CellRange, axis: FillAxis, mode: FillMode, ctx: FillPlanContext): FillPlanResult;
56
+ /**
57
+ * 현재 선택 rect에서 Ctrl+D(아래로)/Ctrl+R(오른쪽으로) 채우기의 source/target rect 산출(순수 함수).
58
+ * 1행(D)/1열(R)뿐이면 채울 대상이 없어 null.
59
+ */
60
+ export declare function ctrlFillSourceTarget(rect: CellRange, axis: 'down' | 'right'): {
61
+ source: CellRange;
62
+ target: CellRange;
63
+ } | null;
@@ -0,0 +1,53 @@
1
+ import { CellCoord, CellRange, Direction, RangeIdentity, RangeModelHost } from './types.js';
2
+ /** anchor/focus → 정규화된 CellRange(§2.3). 역방향 드래그(anchor>focus)도 min/max로 정규화. */
3
+ export declare function normalize(a: CellCoord, f: CellCoord): CellRange;
4
+ export declare class RangeModel {
5
+ private _host;
6
+ private _anchor;
7
+ private _focus;
8
+ private _identity;
9
+ private _rects;
10
+ private _hasSelection;
11
+ private _additive;
12
+ constructor(host: RangeModelHost);
13
+ get hasSelection(): boolean;
14
+ getAnchor(): CellCoord;
15
+ getFocus(): CellCoord;
16
+ getIdentity(): RangeIdentity;
17
+ /** 공개 API 재료(C4): 정규화 rects (없으면 []). MVP는 길이 ≤1. */
18
+ getRangeSelection(): CellRange[];
19
+ /** 공개 API 재료(C4): getRangeSelection()[0] ?? null */
20
+ getActiveRange(): CellRange | null;
21
+ /** 복사/채우기 소스 결정용 별칭(§5.1 getPrimaryRect) */
22
+ getPrimaryRect(): CellRange | null;
23
+ /** 정렬/필터 후에도 유지되는 실제 rowId 집합의 현재 flat 위치(오름차순, 화면밖=-1 제외). */
24
+ getProjectedFlatRows(): number[];
25
+ /** pointerdown. shift=true면 기존 anchor 유지(있을 때만), 아니면 새 1x1 anchor. */
26
+ beginDrag(ri: number, ci: number, opts?: {
27
+ additive?: boolean;
28
+ shift?: boolean;
29
+ }): void;
30
+ /** pointermove. */
31
+ updateFocus(ri: number, ci: number): void;
32
+ /** pointerup — 확정 + 정체성 스냅샷(§2.5). */
33
+ endDrag(): void;
34
+ get additive(): boolean;
35
+ /** 클릭(비-Shift): 새 1×1 anchor(FR-1). */
36
+ click(ri: number, ci: number): void;
37
+ /** Shift+클릭: anchor 유지, focus만 갱신. anchor 없으면 click으로 위임(UC-2 예외). */
38
+ shiftClickExtend(ri: number, ci: number): void;
39
+ /** anchor 고정, focus만 1칸 이동(격자 경계 clamp). 편집 우선순위(C9)는 호출측(KeyboardManager)이 가드. */
40
+ extendFocus(dir: Direction): void;
41
+ setRect(rect: CellRange): void;
42
+ /** clearRangeSelection API 재료. */
43
+ clear(): void;
44
+ /** 현재 rect를 rowId 집합 × field 집합으로 스냅샷(display-index는 렌더용 투영일 뿐). */
45
+ snapshotIdentity(): void;
46
+ /**
47
+ * 정렬/필터 후 호출(onModelReproject 구독 지점). rowId 집합 → 현재 flat 좌표로 재투영.
48
+ * 사라진 행(flatIndexOfRowId === -1)은 정체성에는 남되 투영(rects)에서는 제외된다(불연속 허용).
49
+ * MVP는 단일 bounding rect로 투영(§2.2 rects 길이 1 방침) — 남아있는 행들의 min/max로 계산.
50
+ */
51
+ reproject(): void;
52
+ private _recompute;
53
+ }
@@ -0,0 +1,16 @@
1
+ import { CellRange } from './types.js';
2
+ export interface RangeQueryContext {
3
+ fieldAt(ci: number): string | undefined;
4
+ getCellValue(ri: number, field: string): any;
5
+ }
6
+ /** rect 값 2D 배열(FR-6). */
7
+ export declare function getRangeValues(rect: CellRange, ctx: RangeQueryContext): any[][];
8
+ export interface RangeStats {
9
+ sum: string;
10
+ avg: string;
11
+ count: number;
12
+ min: string;
13
+ max: string;
14
+ }
15
+ /** 숫자 셀에 대해 OGDecimal 기반 sum/avg/count/min/max(FR-6). 숫자 셀이 없으면 null. */
16
+ export declare function getRangeStats(rect: CellRange, ctx: RangeQueryContext): RangeStats | null;
@@ -0,0 +1,47 @@
1
+ import { CellRange } from '../types.js';
2
+ export type { CellRange };
3
+ /** 방향성 원시 좌표. ri=flat/visual index(C0.2), ci=visibleLeaves index(C0.4). */
4
+ export interface CellCoord {
5
+ ri: number;
6
+ ci: number;
7
+ }
8
+ export type Direction = 'up' | 'down' | 'left' | 'right';
9
+ export type FillAxis = Direction;
10
+ export type FillMode = 'copy' | 'series';
11
+ /** 범위 정체성(C0.5) — display-index가 아니라 stable 집합으로 저장. */
12
+ export interface RangeIdentity {
13
+ /** 선택된 data 행의 stable _ogRowId 집합 (정렬/필터를 넘어 보존) */
14
+ rowIds: string[];
15
+ /** 선택된 열의 field 집합 (visibleLeaves.field) */
16
+ fields: string[];
17
+ }
18
+ /** FlatRowModel.resolveFlatRow가 반환하는 참조(C0.3). */
19
+ export interface FlatRowRefLike {
20
+ kind: 'data' | 'group' | 'tree' | 'detailHead' | 'detailFiller';
21
+ rowId?: string;
22
+ dataIndex?: number;
23
+ displayIndex?: number;
24
+ }
25
+ /**
26
+ * F1이 좌표 해소·재투영을 위해 필요로 하는 최소 계약 모양(C0.3 FlatRowModel + visibleLeaves).
27
+ * 실제 구현(baseline FlatRowModel/ColumnLayout)은 이 형태를 만족하는 어댑터를 배선 단계에서 주입한다.
28
+ */
29
+ export interface RangeModelHost {
30
+ /** flat/visual 행 총수 */
31
+ count(): number;
32
+ /** flat index → 참조(kind/rowId 등). 없으면 kind 판별 불가 상태를 반환해야 함(C0.3) */
33
+ resolveFlatRow(flatIndex: number): FlatRowRefLike;
34
+ /** stable rowId → 현재 flat index. 없으면(접힘/필터아웃) -1 */
35
+ flatIndexOfRowId(rowId: string): number;
36
+ /** flat index → stable rowId (data/tree만, 그 외 null) */
37
+ rowIdOfFlat(flatIndex: number): string | null;
38
+ /** 현재 visibleLeaves의 field 목록(순서=ci) */
39
+ visibleFields(): string[];
40
+ }
41
+ /** 채우기 프리뷰(핸들 드래그 중) — 커밋 전 임시 상태 자료(§2.2 FillPreview). */
42
+ export interface FillPreview {
43
+ source: CellRange;
44
+ target: CellRange;
45
+ axis: FillAxis;
46
+ mode: FillMode;
47
+ }
@@ -1,4 +1,4 @@
1
- import { ColumnDef } from '../types.js';
1
+ import { ColumnDef, RendererDef } from '../types.js';
2
2
  export interface RenderContext<T = any> {
3
3
  value: any;
4
4
  row: T;
@@ -8,11 +8,26 @@ export interface RenderContext<T = any> {
8
8
  isSelected: boolean;
9
9
  rowState: 'none' | 'added' | 'edited' | 'removed';
10
10
  displayValue?: string | null;
11
+ /** R1b: per-instance displayFormatter 전략(값·필드·행 → 표시문자열|null). Number/Date 렌더러가
12
+ * ctx.value 위에 적용한다(모듈전역 없이 멀티그리드 격리). null 반환/미설정 시 기본 포맷 폴백.
13
+ * ※ getDisplayValue override(text 경로의 ctx.displayValue)와 달리 **전략만** 적용 — 숫자/날짜의
14
+ * 기본 포맷(천단위·통화·정밀도)을 보존하고 그룹모드 인덱스 불일치를 피한다. */
15
+ displayFormatter?: ((value: any, field: string, row: any) => string | null) | null;
16
+ /** C7(15_cross_contracts.md/F3-R14): 이 셀에 F3 셀 수식이 있으면 true — ColumnDef.formula 재평가를 skip. */
17
+ hasCellFormula?: boolean;
11
18
  }
12
19
  export interface CellRenderer {
13
20
  render(ctx: RenderContext): HTMLElement;
14
21
  }
15
- export declare function setDisplayFormatterResolver(resolver: ((value: any, field: string, row: any) => string | null) | null): void;
22
+ /**
23
+ * R1(OOP 리팩터, DIP 수정): 과거엔 formatNumber/formatDate 가 host 참조가 없어 **모듈 전역**
24
+ * resolver 로 displayFormatter 슬롯에 도달했다. 그 전역은 매 OpenGrid 생성자가 덮어써,
25
+ * 한 페이지에 그리드가 여럿이면 마지막 그리드의 포매터가 전 그리드에 새는 P0 정합성 결함이었다.
26
+ * → 전역을 제거했다. 이제 displayFormatter 는 **per-instance 안전 경로 하나**로만 흐른다:
27
+ * OpenGrid.getDisplayValue(슬롯 읽기) → GridRenderer 가 RenderContext.displayValue 로 주입
28
+ * → 각 셀 렌더러(Text/Number/Date)가 ctx.displayValue 를 우선 사용.
29
+ * formatNumber/formatDate 는 전역 상태 0 의 순수 포맷 함수로 환원했다(출력 동일, 회귀 0).
30
+ */
16
31
  /**
17
32
  * 컬럼에 formula가 있으면 OGDecimal로 평가해 표시값(string)을 반환.
18
33
  * formula가 없으면 null 반환 → 기존 ctx.value 사용.
@@ -60,6 +75,10 @@ export declare class CheckboxRenderer implements CellRenderer {
60
75
  export interface ButtonRendererDef {
61
76
  type: 'button';
62
77
  label?: string | ((value: any, row: any) => string);
78
+ /** R12c: 라벨과 함께 표시할 아이콘 role/key(renderIcon). 미지정 시 라벨만(기존과 동일). */
79
+ icon?: string;
80
+ /** 아이콘 위치(기본 'left'). */
81
+ iconPos?: 'left' | 'right';
63
82
  buttonClass?: string;
64
83
  style?: string;
65
84
  }
@@ -147,4 +166,23 @@ export declare class HtmlRenderer implements CellRenderer {
147
166
  export declare class BarcodeRenderer implements CellRenderer {
148
167
  render(ctx: RenderContext): HTMLElement;
149
168
  }
169
+ /**
170
+ * R10(§6-R10, §2.5 R-4c, §3.1 C11): `createRenderer` 이중 switch 를 `Map<typeName, factory>`
171
+ * 레지스트리로 대체한다. 내장 타입은 모듈 로드시 부트스트랩 등록(아래 switch 와 동일 매핑),
172
+ * `createRenderer` 는 레지스트리로 해석하고 미등록 타입은 기존과 동일하게 TextRenderer 로 폴백한다.
173
+ * `registerRenderer(typeName, factory)` 로 코어 편집 없이 커스텀 렌더러를 추가할 수 있다(OCP).
174
+ *
175
+ * 등록은 **프로세스 전역**(내장은 불변에 가깝고, 커스텀 등록은 defaultOverride 와 동형의 전역 정책).
176
+ * 인스턴스별 스코핑은 R11/R12(ExtensionPointRegistry)의 후속 작업으로 남긴다.
177
+ *
178
+ * 팩토리는 `(col, def)` 를 받는다. `def` 는 RendererDef 객체 경로에서만 채워지며(문자열/col.type
179
+ * 경로에서는 undefined), 원 switch 의 세 컨텍스트(col.type / 문자열 / 객체) 동작을 정확히 보존한다:
180
+ * - image/progress/sparkline/rating/template 은 def(설정 객체) 없이는 원래 TextRenderer 로 떨어졌으므로
181
+ * def 유무로 게이트한다(문자열 렌더러명만 준 미완성 설정 = 기존과 동일 폴백).
182
+ */
183
+ export type RendererFactory = (col: ColumnDef, def?: RendererDef) => CellRenderer;
184
+ /** 커스텀 셀 렌더러 타입을 코어 편집 없이 등록(OCP). 프로세스 전역. */
185
+ export declare function registerRenderer(typeName: string, factory: RendererFactory): void;
186
+ /** 등록 여부 조회(내부/테스트용). */
187
+ export declare function hasRenderer(typeName: string): boolean;
150
188
  export declare function createRenderer(col: ColumnDef): CellRenderer;
@@ -1,3 +1,5 @@
1
+ import { FormulaErrorCode } from './formula/types.js';
2
+ import { RangeStats as _RangeStats } from './range/RangeQuery.js';
1
3
  export type DataType = 'string' | 'number' | 'date' | 'boolean' | 'select' | 'radio' | 'img' | 'html' | 'barcode';
2
4
  export type { MaskType, MaskDef } from './MaskingEngine.js';
3
5
  export type SelectionMode = 'single' | 'row' | 'multiple' | 'cells';
@@ -103,12 +105,144 @@ export interface SelectionEvent<T = any> {
103
105
  rowIndexes: number[];
104
106
  cells?: CellRange[];
105
107
  }
108
+ /**
109
+ * CellRangeSemantics — CellRange 의미 규범(C0.4, 15_cross_contracts.md). 소유자 = F1(범위 선택).
110
+ * F3(수식 ref)·F4(차트 소스)는 이 의미로만 CellRange 를 소비한다.
111
+ * - startRow/endRow : flat/visual index (C0.2 — FlatRowModel 이 다루는 화면 표시 순서).
112
+ * group/tree pseudo-row, (F2 도입 후) detail head/filler 도 포함한 인덱스 공간이며,
113
+ * display index(정렬/필터만 반영, group/tree 제외)와 다르다.
114
+ * - startCol/endCol : `ColumnLayout.visibleLeaves` 인덱스(숨김 컬럼 제외). 숨김 컬럼은
115
+ * 좌표를 흔들지 않되, 언하이드 시 재렌더로 좌표 표시(A1 등)가 갱신된다.
116
+ * - 선택 자체의 영속 정체성은 이 인덱스가 아니라 stable (rowId × field) 앵커로 저장한다
117
+ * (C0.5) — CellRange 는 어디까지나 "현재 화면에 투영된" 사각형 표현이다.
118
+ */
106
119
  export interface CellRange {
107
120
  startRow: number;
108
121
  endRow: number;
109
122
  startCol: number;
110
123
  endCol: number;
111
124
  }
125
+ export interface RangeSelectionOptions {
126
+ /** 기본 selection==='cells' 와 동치 */
127
+ enabled?: boolean;
128
+ /** 기본 true — 핸들 표시/드래그 */
129
+ fillHandle?: boolean;
130
+ /** 기본 false — Ctrl 멀티 rect(Full, 미구현) */
131
+ multiRange?: boolean;
132
+ /** 기본 24(px) — autoscroll 밴드 폭 */
133
+ autoScrollEdge?: number;
134
+ /** 기본 true — false 면 항상 copy(시리즈 감지 비활성) */
135
+ seriesFill?: boolean;
136
+ /** 기본 false — 그룹/트리 모드 범위선택(MVP 비활성) */
137
+ enabledInTreeGroup?: boolean;
138
+ /** 기본 false — 수식 대상 덮어쓰기(C3.2 opt-in) */
139
+ fillOverwriteFormula?: boolean;
140
+ }
141
+ export interface RangeFillEvent {
142
+ source: CellRange;
143
+ target: CellRange;
144
+ mode: 'copy' | 'series';
145
+ written: Array<{
146
+ rowIndex: number;
147
+ field: string;
148
+ oldValue: any;
149
+ newValue: any;
150
+ }>;
151
+ skippedFormula?: number;
152
+ /** before 훅에서 true 로 바꾸면 채우기 취소(현재 배선은 이벤트 emit 뒤 즉시 확인) */
153
+ cancel?: boolean;
154
+ }
155
+ export interface RangeCopyEvent {
156
+ range: CellRange;
157
+ text: string;
158
+ }
159
+ export interface RangeChangeEvent {
160
+ range: CellRange | null;
161
+ }
162
+ export type { FormulaErrorCode } from './formula/types.js';
163
+ /** F3 옵션(C5.1 단일 중첩 — 최상위 flat 키 금지). */
164
+ export interface FormulaOptions {
165
+ /** 셀 수식 인-셀 '=' 편집 자동 인식 on(기본 false — 회귀 0). setCellFormula API 는 이 값과 무관하게 항상 동작. */
166
+ enabled?: boolean;
167
+ /** 참조 정규화 정책(기본 'stable', §3.2). */
168
+ refMode?: 'stable' | 'relative';
169
+ /** 나눗셈 소수 자리(기본 30, FormulaEngine 계승). */
170
+ divisionPrecision?: number;
171
+ /** 수식 바 표시(P1, 기본 false — 미구현). */
172
+ formulaBar?: boolean;
173
+ /** 수식 셀 마커(기본 true — HANMS-09/R-FORMULA-MARKER). */
174
+ cellMarker?: boolean;
175
+ /** 편집 시 자동 재계산(기본 true). */
176
+ autoRecalc?: boolean;
177
+ onFormulaChange?: (e: FormulaChangeEvent) => void;
178
+ onFormulaRecalc?: (e: FormulaRecalcEvent) => void;
179
+ onFormulaError?: (e: FormulaErrorEvent) => void;
180
+ }
181
+ export interface FormulaChangeEvent {
182
+ rowIndex: number;
183
+ field: string;
184
+ formula: string;
185
+ oldFormula: string | null;
186
+ }
187
+ export interface FormulaRecalcEvent {
188
+ changed: string[];
189
+ cycles: number;
190
+ ms: number;
191
+ /** Spike-A §8 교훈: 폐포가 임계(500) 초과 시 true(가이드 문서화/모니터링용). */
192
+ large: boolean;
193
+ }
194
+ export interface FormulaErrorEvent {
195
+ rowIndex: number;
196
+ field: string;
197
+ error: FormulaErrorCode;
198
+ }
199
+ export type { RangeStats } from './range/RangeQuery.js';
200
+ /** masterDetail.renderer 3번째 인자(§6.1). */
201
+ export interface DetailRenderApi<T = any> {
202
+ grid: OpenGridInstance<T>;
203
+ rowId: string;
204
+ /** 현재 그리드의 중첩 깊이(CON-4). 0 = 최상위. */
205
+ depth: number;
206
+ collapse: () => void;
207
+ /** 패널 재측정(Phase2 auto 대비 자리 — MVP 는 no-op 에 가까움). */
208
+ refresh: () => void;
209
+ }
210
+ /** F2 옵션(C5.1 단일 중첩 — 구 flat `detail*`/`masterDetail:boolean` 은 이 안으로 접힘). */
211
+ export interface MasterDetailOptions<T = any> {
212
+ /** 기능 on/off. 기본 false. */
213
+ enabled?: boolean;
214
+ /** 임의 HTML/컴포넌트를 host 에 주입(§5). subgridOptions 와 동시 지정 시 이 쪽이 우선. */
215
+ renderer?: (row: T, host: HTMLElement, api: DetailRenderApi<T>) => void | HTMLElement;
216
+ /** 패널 높이(px). 기본 200. MVP 는 rowHeight 배수로 양자화(EC-10). */
217
+ height?: number;
218
+ /**
219
+ * 'fixed'(기본)만 MVP 에서 동작. 'auto' 는 Spike-B(C12.2) 통과 전 미공개 — 지정해도
220
+ * DetailManager 가 'fixed' 로 무시 처리하고 1회 console.warn 한다.
221
+ */
222
+ heightMode?: 'fixed' | 'auto';
223
+ /** 기본 true. false = 아코디언(펼침 1개만 허용). */
224
+ expandMultiple?: boolean;
225
+ /** 기본 false. true 면 collapse 해도 host/instance 캐시를 유지(재펼침 시 재생성 생략). */
226
+ cache?: boolean;
227
+ /** 어포던스 위치. 기본 'expander-col'(전용 컬럼). */
228
+ toggle?: 'expander-col' | 'first-cell';
229
+ /** 패널 role=region 의 aria-label. 기본 '상세 내용'. */
230
+ ariaLabel?: string;
231
+ /** 중첩 깊이 한계(CON-4/FR-10). 기본 2. */
232
+ maxDepth?: number;
233
+ /** 지정 시 height 대신 이 값을 슬롯수(정수, 최소 1)로 직접 사용. */
234
+ detailRowCount?: number;
235
+ /** renderer 미지정 시: 자식 OpenGrid 를 이 옵션으로 자동 생성(§5 ②). */
236
+ subgridOptions?: GridOptions<any>;
237
+ }
238
+ /** rowExpand/rowCollapse payload(C5.2, §6.3). */
239
+ export interface RowExpandEvent<T = any> {
240
+ /** flat/visual index(C0.2). */
241
+ rowIndex: number;
242
+ rowId: string;
243
+ row: T;
244
+ host: HTMLElement | null;
245
+ }
112
246
  export interface RendererDef {
113
247
  type: RendererType;
114
248
  [key: string]: any;
@@ -281,12 +415,31 @@ export interface GridOptions<T = any> {
281
415
  autoHeight?: boolean;
282
416
  fillWidth?: boolean;
283
417
  defaultColumnWidth?: number;
418
+ /**
419
+ * 뷰포트 안전장치(옵트인, 기본 undefined = OFF = 기존 동작 완전 불변).
420
+ * 호스트가 그리드 컨테이너 조상 체인에 확정 높이(definite height)를 주지 않으면
421
+ * 내부 스페이서(totalRows×rowHeight)가 컨테이너를 전체 콘텐츠 크기로 부풀리고,
422
+ * ResizeObserver 되먹임으로 windowing 이 무력화되어 전 행이 DOM 렌더되는 폭주가 발생한다
423
+ * (대량 데이터일수록 재앙적). 이 값을 지정하면, 컨테이너가 전 콘텐츠를 다 담는 "언바운드"
424
+ * 상태로 감지될 때에 한해 윈도잉 뷰포트 높이를 이 값(px)으로 클램프해 폭주를 차단한다.
425
+ * 정상적으로 확정 높이가 있는 바운드 컨테이너에는 영향이 없다.
426
+ * 1순위 권장은 컨테이너/그리드에 확정 height 를 주는 것이며, 이 옵션은 안전망이다.
427
+ */
428
+ fallbackViewportHeight?: number;
284
429
  editable?: boolean;
285
430
  editMode?: 'click' | 'dblclick' | 'none';
286
431
  history?: boolean;
287
432
  historySize?: number;
288
433
  selection?: SelectionMode;
289
434
  clipboard?: boolean;
435
+ /** F1: 범위 선택 + 채우기 핸들(C5.1 단일 중첩 — 최상위 flat 키 금지). */
436
+ rangeSelection?: RangeSelectionOptions;
437
+ /** F3: 셀 수식(C5.1 단일 중첩). */
438
+ formula?: FormulaOptions;
439
+ /** F2: 마스터/디테일(C5.1 단일 중첩). */
440
+ masterDetail?: MasterDetailOptions<T>;
441
+ /** F4: 그리드 데이터 통합 차트(C5.1 단일 중첩). 타입은 chart/types 순환-안전 type-only import. */
442
+ chart?: import('./chart/types.js').ChartGlobalOptions;
290
443
  sortable?: boolean;
291
444
  multiSort?: boolean;
292
445
  filterable?: boolean;
@@ -320,6 +473,7 @@ export interface GridOptions<T = any> {
320
473
  tooltips?: boolean;
321
474
  ariaLabel?: string;
322
475
  theme?: string;
476
+ skin?: string;
323
477
  cssVars?: Record<string, string>;
324
478
  contextMenu?: boolean | ContextMenuItem[];
325
479
  worksheets?: WorksheetDef[];
@@ -334,6 +488,15 @@ export interface GridOptions<T = any> {
334
488
  onEditBefore?: (e: EditEvent<T>) => boolean;
335
489
  onRowClick?: (e: RowEvent<T>) => void;
336
490
  onSelectionChange?: (e: SelectionEvent<T>) => void;
491
+ /** F1: 범위 rects 변경 시(C4, F4 라이브 소비) */
492
+ onRangeChange?: (e: RangeChangeEvent) => void;
493
+ /** F1: 채우기 커밋 결과(§6.3) */
494
+ onRangeFill?: (e: RangeFillEvent) => void;
495
+ /** F1: 범위 복사 시(§6.3) */
496
+ onRangeCopy?: (e: RangeCopyEvent) => void;
497
+ /** F2: 행 상세 패널 펼침/접힘 시(C5.1 on* 버킷). */
498
+ onRowExpand?: (e: RowExpandEvent<T>) => void;
499
+ onRowCollapse?: (e: RowExpandEvent<T>) => void;
337
500
  onSortChange?: (e: SortEvent) => void;
338
501
  onFilterChange?: (e: FilterEvent) => void;
339
502
  onScroll?: (e: ScrollEvent) => void;
@@ -379,8 +542,15 @@ export interface OverrideCallOptions {
379
542
  /** 'fallback' → 레이어 예외 시 경고 후 원본 실행(멱등 가정, 롤백 불가). 미지정 시 strict. */
380
543
  onError?: 'fallback';
381
544
  }
382
- /** 등록 가능한 알고리즘 슬롯 이름(6종). */
383
- export type StrategySlot = 'sortComparator' | 'filterPredicate' | 'displayFormatter' | 'cellSerializer' | 'groupKeyFn' | 'summaryOp';
545
+ /** 등록 가능한 알고리즘 슬롯 이름. */
546
+ export type StrategySlot = 'sortComparator' | 'filterPredicate' | 'displayFormatter' | 'cellSerializer' | 'groupKeyFn' | 'summaryOp' | 'cellClassResolver' | 'ariaLabelResolver' | 'skinResolver';
547
+ /**
548
+ * SKIN 토큰 이름 집합 — **형태(FORM)만** 소유(색 0). COLOR 토큰과 disjoint name set 이라
549
+ * 색⊥형태 직교성이 이름 충돌 부재로 물리적으로 보장된다(item3 §1.1~1.2, HANMS §4).
550
+ */
551
+ export type SkinTokenName = '--og-radius-none' | '--og-radius-sm' | '--og-radius-md' | '--og-radius-lg' | '--og-radius-pill' | '--og-radius-container' | '--og-radius-control' | '--og-radius-widget' | '--og-container-radius' | '--og-border-width' | '--og-border-width-strong' | '--og-border-style' | '--og-divider-style' | '--og-divider-repeat' | '--og-elevation-sm' | '--og-elevation-md' | '--og-elevation-lg' | '--og-elevation-alpha-sm' | '--og-elevation-alpha-md' | '--og-elevation-alpha-lg' | '--og-elevation-inset' | '--og-cell-padding-x' | '--og-cell-padding-y' | '--og-density-row-height' | '--og-density-header-height' | '--og-density-footer-height' | '--og-scrollbar-size' | '--og-texture-bg' | '--og-texture-size' | '--og-texture-opacity' | '--og-focus-width' | '--og-focus-style' | '--og-focus-offset' | '--og-focus-radius' | '--og-icon-size' | '--og-icon-fill' | '--og-icon-stroke-width' | '--og-icon-corner' | '--og-transition-fast' | '--og-transition-base' | '--og-row-accent-width';
552
+ /** FORM-only 스킨 델타. 값에 색 리터럴이 있으면 SkinRegistry 가 런타임 거부(Rule 2, 직교성). */
553
+ export type SkinTokenDelta = Partial<Record<SkinTokenName, string>>;
384
554
  /** 단일키 정렬 비교자. dir 부호는 호출자(DataLayer)가 적용 — 슬롯은 비교만 반환. */
385
555
  export type SortComparatorFn = (a: any, b: any, field: string, dir: 'asc' | 'desc') => number;
386
556
  /** 필터 술어. true → 행 포함. */
@@ -393,6 +563,15 @@ export type CellSerializerFn = (value: any, col: any, row: any) => any;
393
563
  export type GroupKeyFn = (row: any, remainingFields: string[]) => any;
394
564
  /** 집계 연산. null 반환 시 기본 SUM/AVG/COUNT/MAX/MIN 분기로 폴백. */
395
565
  export type SummaryOpFn = (op: string, nums: any[], field: string) => number | null;
566
+ /** R11(§4.2): 셀 클래스 렌더훅 리졸버. 렌더층이 셀 element 에 추가할 className(null=미참여). */
567
+ export type CellClassResolverFn = (value: any, field: string, row: any) => string | null;
568
+ /** R11(§4.2): 셀 aria-label 렌더훅 리졸버. 렌더층이 셀 aria-label 을 대체(null=기본 유지). */
569
+ export type AriaLabelResolverFn = (value: any, field: string, row: any) => string | null;
570
+ /**
571
+ * F1 채우기 시리즈 커스텀 리졸버 슬롯(C5.3, 예약). 사용자가 날짜/커스텀 시리즈를 주입할 수 있다.
572
+ * ⚠️ 슬롯 등록 경로만 확보되어 있으며, RangeSelectionManager/FillEngine 소비 배선은 F1-b(Full) 대상.
573
+ */
574
+ export type FillSeriesResolverFn = (sourceLine: any[], k: number, axisSign: 1 | -1) => any;
396
575
  /** 슬롯명 → 시그니처 매핑. */
397
576
  export interface StrategyMap {
398
577
  sortComparator: SortComparatorFn;
@@ -401,10 +580,33 @@ export interface StrategyMap {
401
580
  cellSerializer: CellSerializerFn;
402
581
  groupKeyFn: GroupKeyFn;
403
582
  summaryOp: SummaryOpFn;
583
+ fillSeriesResolver: FillSeriesResolverFn;
584
+ cellClassResolver: CellClassResolverFn;
585
+ ariaLabelResolver: AriaLabelResolverFn;
586
+ skinResolver: SkinResolverFn;
587
+ }
588
+ /**
589
+ * R12b(item3 §6.1): 스킨 FORM 해석 인터셉트 슬롯. AppearanceResolver 가 fallback 과 함께 읽어(제로코스트)
590
+ * 오버라이드가 form 토큰 델타를 통째로 가로챌 수 있다. 미설정 시 내장 스킨 카탈로그가 그대로 적용.
591
+ */
592
+ export type SkinResolverFn = (skinId: string) => SkinTokenDelta | null;
593
+ /**
594
+ * R11(§4.3, T-ζ): SemVer 보증되는 **타입드 override 카탈로그**(좁은 "지원됨" 문).
595
+ * `override("anyMethod", fn)` 문자열 탈출구(UC-11, best-effort)는 그대로 열려 있고 —
596
+ * 이 인터페이스는 축복된(blessed) 확장점 이름을 IDE 발견가능하게 좁게 표시할 뿐, 넓은 문을 닫지 않는다.
597
+ * 각 항목은 소비 테스트를 동반한다(유령 확장점 금지, DeMarco M9b).
598
+ */
599
+ export interface OverridePoints<T = any> {
600
+ /** 셀 표시 텍스트 해석(렌더훅 displayText 의 근원). */
601
+ getDisplayValue(rowIndex: number, field: string): string;
602
+ /** 원시 셀 값 접근. */
603
+ readCell(rowIndex: number, field: string): any;
404
604
  }
405
605
  /** 호출가능 + .strategy 멤버를 가진 하이브리드 override API. */
406
606
  export interface OverrideApi<T = any> {
407
- /** 메서드 본문 무수정 런타임 래핑(C1-clean). 체이닝 위해 grid 인스턴스 반환. */
607
+ /** R11(§4.3): 타입드 오버로드 축복된 확장점 이름(IDE 발견). SemVer 보증 카탈로그. */
608
+ <K extends keyof OverridePoints<T>>(name: K, fn: OverrideLayerFn, opts?: OverrideCallOptions): OpenGridInstance<T>;
609
+ /** 메서드 본문 무수정 런타임 래핑(C1-clean, 탈출구 UC-11). 체이닝 위해 grid 인스턴스 반환. */
408
610
  (name: string, fn: OverrideLayerFn, opts?: OverrideCallOptions): OpenGridInstance<T>;
409
611
  /** 알고리즘 슬롯 등록(Phase 2 매니저 훅포인트). 체이닝 위해 grid 인스턴스 반환. */
410
612
  strategy<K extends StrategySlot>(slot: K, fn: StrategyMap[K]): OpenGridInstance<T>;
@@ -439,6 +641,21 @@ export interface OpenGridInstance<T = any> {
439
641
  getDisplayValue(rowIndex: number, field: string): string;
440
642
  writeCell(rowIndex: number, field: string, value: any): void;
441
643
  getRowAt(rowIndex: number): T;
644
+ /** flat/visual index ↔ data 리졸버. F1/F3/F4 는 이 모델을 경유해 대상을 해소한다. */
645
+ getFlatRowModel(): import('./FlatRowModel.js').FlatRowModel;
646
+ /** 배치 쓰기 시작 — 이후 writeCell 들의 render/dataChange 를 지연·coalesce(reentrant). */
647
+ beginBatch(): void;
648
+ /** 배치 종료 — 배치 중 쓰기가 있었으면 1회 render + 1회 coalesced dataChange. */
649
+ endBatch(): void;
650
+ /**
651
+ * beginBatch+루프+endBatch 래퍼. rowIndex 는 flat index — kind!=='data' 대상(group/tree/
652
+ * detail 의사행)은 쓰기 전에 skip 한다(C0.3 쓰기 안전). 반환값 = 건너뛴 셀 수.
653
+ */
654
+ writeCells(patches: Array<{
655
+ rowIndex: number;
656
+ field: string;
657
+ value: any;
658
+ }>): number;
442
659
  getChanges(): {
443
660
  added: T[];
444
661
  edited: T[];
@@ -480,6 +697,64 @@ export interface OpenGridInstance<T = any> {
480
697
  getActiveRow(): number;
481
698
  activate(index: number): void;
482
699
  deselect(): void;
700
+ /** 정규화 rects(없으면 []). MVP 는 길이 ≤1. */
701
+ getRangeSelection(): CellRange[];
702
+ /** = getRangeSelection()[0] ?? null(C4, F4 소비). */
703
+ getActiveRange(): CellRange | null;
704
+ setRangeSelection(range: CellRange | CellRange[]): void;
705
+ clearRangeSelection(): void;
706
+ /** 현재 활성 범위의 값 2D 배열(FR-6, F4 필수 계약). */
707
+ getRangeValues(): any[][];
708
+ /** 현재 활성 범위 숫자 셀의 OGDecimal 기반 통계(FR-6, F4 필수 계약). */
709
+ getRangeStats(): _RangeStats | null;
710
+ /** source→target 채우기(배치 경유, C2). axis 는 두 rect 상대 위치로 추론. */
711
+ fillRange(source: CellRange, target: CellRange, mode?: 'copy' | 'series'): void;
712
+ createChart(config: import('./chart/types.js').ChartConfig): import('./chart/types.js').ChartInstance;
713
+ getCharts(): import('./chart/types.js').ChartInstance[];
714
+ destroyCharts(): void;
715
+ /** "=A1+B2" 형태. rowIndex 는 flat(C0), 내부 즉시 stable rowId 로 정규화. */
716
+ setCellFormula(rowIndex: number, field: string, formula: string): void;
717
+ getCellFormula(rowIndex: number, field: string): string | null;
718
+ hasCellFormula(rowIndex: number, field: string): boolean;
719
+ /** 수식 제거(값은 유지). */
720
+ clearCellFormula(rowIndex: number, field: string): void;
721
+ getCellError(rowIndex: number, field: string): FormulaErrorCode | null;
722
+ /** 디버깅용 — 이 셀을 참조하는(종속) 셀들. */
723
+ getDependents(rowIndex: number, field: string): Array<{
724
+ rowIndex: number;
725
+ field: string;
726
+ }>;
727
+ /** 디버깅용 — 이 셀이 참조하는(선행) 셀들. */
728
+ getPrecedents(rowIndex: number, field: string): Array<{
729
+ rowIndex: number;
730
+ field: string;
731
+ }>;
732
+ /** 전체 수식 위상 재계산(setData/컬럼 변경 등). */
733
+ recalculate(): void;
734
+ /** 단일 셀 + 종속 폐포만 재계산. */
735
+ recalculateCell(rowIndex: number, field: string): void;
736
+ /** C3(F1 fill 전용): srcRowId/srcField 수식의 상대축만 dRow/dCol 오프셋한 새 수식 원문. */
737
+ offsetFormula(srcRowId: string, srcField: string, dRow: number, dCol: number): string;
738
+ /** rowRef 는 flat/visual index(C0.2) 또는 stable id. maxDepth 초과 시 거부(announce, FR-10). */
739
+ expandRow(rowRef: number | {
740
+ id: string;
741
+ }): void;
742
+ collapseRow(rowRef: number | {
743
+ id: string;
744
+ }): void;
745
+ toggleRow(rowRef: number | {
746
+ id: string;
747
+ }): void;
748
+ isRowExpanded(rowRef: number | {
749
+ id: string;
750
+ }): boolean;
751
+ collapseAllDetails(): void;
752
+ /** 펼쳐진 적 없으면 undefined. renderer 반환값 또는 자동 생성 서브그리드 인스턴스. */
753
+ getDetailInstance<D = any>(rowRef: number | {
754
+ id: string;
755
+ }): D | undefined;
756
+ /** FR-11: 컬럼/호스트 리사이즈 후 열린 패널 폭을 강제 재동기(보통은 재렌더가 자동 처리). */
757
+ resyncPanelWidths(): void;
483
758
  getChecked(): Array<{
484
759
  row: T;
485
760
  rowIndex: number;
@@ -526,6 +801,12 @@ export interface OpenGridInstance<T = any> {
526
801
  resize(width?: number, height?: number): void;
527
802
  setTheme(theme: string): void;
528
803
  setThemeVar(varName: string, value: string): void;
804
+ /** R12b: 스킨(FORM 축) 전환 — data-og-skin 설정 + 인라인 form 사이트 재해석. 색 테마와 직교. */
805
+ setSkin(skin: string): void;
806
+ /** R12b: 현재 스킨 id('default' = 오늘). */
807
+ getSkin(): string;
808
+ /** R12b: FORM 축 단일 토큰 런타임 오버라이드(setThemeVar 의 형태-축 형제). 색 값은 거부. */
809
+ setSkinVar(varName: string, value: string): void;
529
810
  destroy(): void;
530
811
  setOptions(opts: Partial<GridOptions<T>>): void;
531
812
  /** 컬럼 마스킹 ON/OFF. enabled=true → 마스킹 적용, enabled=false → 전체 해제 */
@@ -575,6 +856,7 @@ export interface ContextMenuItem {
575
856
  type?: 'divider';
576
857
  }
577
858
  export type { FilterSelectColumn, FilterSelectConfig } from './FilterSelect.js';
859
+ export type { FlatRowRef } from './FlatRowModel.js';
578
860
  export interface WorksheetDef<T = any> {
579
861
  name: string;
580
862
  columns?: ColumnDef<T>[];