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.
- package/CHANGELOG.md +44 -0
- package/THIRD_PARTY_LICENSES.txt +43 -0
- package/dist/OpenGrid-LcZ5iixx.cjs +97 -0
- package/dist/OpenGrid-yg4mw6Ge.js +9505 -0
- package/dist/open-grid-base.css +66 -5
- package/dist/open-grid-react.cjs +1 -1
- package/dist/open-grid-react.js +1 -1
- package/dist/open-grid-skins.css +111 -0
- package/dist/open-grid-themes.css +96 -1
- package/dist/open-grid-vue.cjs +1 -1
- package/dist/open-grid-vue.js +1 -1
- package/dist/open-grid.cjs +3 -3
- package/dist/open-grid.js +129 -119
- package/dist/types/core/AppearanceResolver.d.ts +100 -0
- package/dist/types/core/CellEditManager.d.ts +4 -0
- package/dist/types/core/CellEventHandler.d.ts +6 -0
- package/dist/types/core/ChartManager.d.ts +58 -0
- package/dist/types/core/CrossGridController.d.ts +70 -0
- package/dist/types/core/DataLayer.d.ts +17 -0
- package/dist/types/core/DetailManager.d.ts +72 -0
- package/dist/types/core/ExtensionPointRegistry.d.ts +92 -0
- package/dist/types/core/FlatRowModel.d.ts +56 -0
- package/dist/types/core/FormulaController.d.ts +79 -0
- package/dist/types/core/GridComposer.d.ts +137 -0
- package/dist/types/core/GridRenderer.d.ts +73 -4
- package/dist/types/core/GroupTreeManager.d.ts +13 -0
- package/dist/types/core/IconRegistry.d.ts +55 -0
- package/dist/types/core/KeyboardManager.d.ts +19 -0
- package/dist/types/core/MutationService.d.ts +126 -0
- package/dist/types/core/OpenGrid.d.ts +167 -22
- package/dist/types/core/OrgChart.d.ts +2 -0
- package/dist/types/core/RangeSelectionManager.d.ts +95 -0
- package/dist/types/core/RenderController.d.ts +65 -0
- package/dist/types/core/SkinRegistry.d.ts +53 -0
- package/dist/types/core/SortFilterManager.d.ts +2 -0
- package/dist/types/core/chart/CanvasAdapter.d.ts +52 -0
- package/dist/types/core/chart/DataExtractor.d.ts +49 -0
- package/dist/types/core/chart/a11y.d.ts +21 -0
- package/dist/types/core/chart/downsample.d.ts +25 -0
- package/dist/types/core/chart/hittest.d.ts +20 -0
- package/dist/types/core/chart/palette.d.ts +56 -0
- package/dist/types/core/chart/scales.d.ts +24 -0
- package/dist/types/core/chart/types.d.ts +181 -0
- package/dist/types/core/detail/DetailGlyph.d.ts +48 -0
- package/dist/types/core/detail/DetailSplice.d.ts +67 -0
- package/dist/types/core/detail/DetailState.d.ts +67 -0
- package/dist/types/core/detail/SubgridCache.d.ts +73 -0
- package/dist/types/core/detail/index.d.ts +14 -0
- package/dist/types/core/editors/CellEditor.d.ts +17 -1
- package/dist/types/core/formula/FormulaEvaluator.d.ts +15 -0
- package/dist/types/core/formula/FormulaGraph.d.ts +43 -0
- package/dist/types/core/formula/FormulaParser.d.ts +6 -0
- package/dist/types/core/formula/FormulaStore.d.ts +17 -0
- package/dist/types/core/formula/RecalcCoordinator.d.ts +85 -0
- package/dist/types/core/formula/normalizeRefs.d.ts +15 -0
- package/dist/types/core/formula/numericLiteral.d.ts +7 -0
- package/dist/types/core/formula/serializeFormula.d.ts +6 -0
- package/dist/types/core/formula/types.d.ts +104 -0
- package/dist/types/core/icons/bootstrap-icons.d.ts +9 -0
- package/dist/types/core/range/ClipboardCodec.d.ts +30 -0
- package/dist/types/core/range/FillEngine.d.ts +63 -0
- package/dist/types/core/range/RangeModel.d.ts +53 -0
- package/dist/types/core/range/RangeQuery.d.ts +16 -0
- package/dist/types/core/range/types.d.ts +47 -0
- package/dist/types/core/renderers/CellRenderer.d.ts +40 -2
- package/dist/types/core/types.d.ts +285 -3
- package/dist/types/index.d.ts +6 -1
- package/package.json +1 -1
- package/dist/OpenGrid-CZRcxruq.cjs +0 -90
- package/dist/OpenGrid-Cjv7Os5a.js +0 -4871
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { DataLayer } from './DataLayer.js';
|
|
2
|
+
import { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
+
import { GridRenderer } from './GridRenderer.js';
|
|
4
|
+
import { CellEditManager } from './CellEditManager.js';
|
|
5
|
+
import { FlatRowModel } from './FlatRowModel.js';
|
|
6
|
+
import { GridOptions } from './types.js';
|
|
7
|
+
import { RangeStats } from './range/RangeQuery.js';
|
|
8
|
+
import { CellRange, Direction, FillMode, FillPreview } from './range/types.js';
|
|
9
|
+
export interface RangeSelectionDeps<T extends Record<string, any>> {
|
|
10
|
+
getOptions: () => Required<GridOptions<T>>;
|
|
11
|
+
getData: () => DataLayer<T>;
|
|
12
|
+
getColLayout: () => ColumnLayout<T>;
|
|
13
|
+
getFlatModel: () => FlatRowModel;
|
|
14
|
+
getRenderer: () => GridRenderer | null;
|
|
15
|
+
getEditMgr: () => CellEditManager<T>;
|
|
16
|
+
setFocusCell: (ri: number, ci: number) => void;
|
|
17
|
+
writeCells: (patches: Array<{
|
|
18
|
+
rowIndex: number;
|
|
19
|
+
field: string;
|
|
20
|
+
value: any;
|
|
21
|
+
}>) => number;
|
|
22
|
+
getDisplayValue: (ri: number, field: string) => string;
|
|
23
|
+
emit: (event: string, ...args: any[]) => void;
|
|
24
|
+
doRender: () => void;
|
|
25
|
+
announce: (msg: string) => void;
|
|
26
|
+
hasCellFormula?: (rowId: string, field: string) => boolean;
|
|
27
|
+
offsetFormula?: (rowId: string, field: string, dRow: number, dCol: number) => string;
|
|
28
|
+
setCellFormulaByRowId?: (rowId: string, field: string, formula: string) => void;
|
|
29
|
+
}
|
|
30
|
+
export declare class RangeSelectionManager<T extends Record<string, any> = any> {
|
|
31
|
+
private _d;
|
|
32
|
+
private _model;
|
|
33
|
+
private _isDragging;
|
|
34
|
+
private _fillDragSource;
|
|
35
|
+
private _fillDragStart;
|
|
36
|
+
private _fillPreview;
|
|
37
|
+
private _handlePointerId;
|
|
38
|
+
private _autoScrollRAF;
|
|
39
|
+
private _autoScrollVX;
|
|
40
|
+
private _autoScrollVY;
|
|
41
|
+
private _overlayEl;
|
|
42
|
+
private _borderEl;
|
|
43
|
+
private _previewEl;
|
|
44
|
+
private _handleEl;
|
|
45
|
+
private _mountedWrap;
|
|
46
|
+
constructor(deps: RangeSelectionDeps<T>);
|
|
47
|
+
isEnabled(): boolean;
|
|
48
|
+
private _rangeOpts;
|
|
49
|
+
private _editorActive;
|
|
50
|
+
hasSelection(): boolean;
|
|
51
|
+
getRangeSelection(): CellRange[];
|
|
52
|
+
getActiveRange(): CellRange | null;
|
|
53
|
+
getFillPreview(): FillPreview | null;
|
|
54
|
+
getRangeValues(): any[][];
|
|
55
|
+
getRangeStats(): RangeStats | null;
|
|
56
|
+
private _queryCtx;
|
|
57
|
+
handleCellMouseDown(ri: number, ci: number, e: MouseEvent): void;
|
|
58
|
+
handleCellMouseMove(ri: number, ci: number, e: MouseEvent): void;
|
|
59
|
+
handleCellMouseUp(_ri: number, _ci: number, _e: MouseEvent): void;
|
|
60
|
+
handleClick(ri: number, ci: number, shiftKey: boolean): void;
|
|
61
|
+
extendFocus(dir: Direction): void;
|
|
62
|
+
clear(): void;
|
|
63
|
+
clearRangeSelection(): void;
|
|
64
|
+
setRangeSelection(range: CellRange | CellRange[]): void;
|
|
65
|
+
/** applySort/applyFilter 직후 호출(C0.5, §2.5) — 선택은 rowId 집합 기준으로 재투영(해제 아님). */
|
|
66
|
+
reproject(): void;
|
|
67
|
+
private _afterModelChange;
|
|
68
|
+
private _announceSelection;
|
|
69
|
+
ctrlFill(axis: 'down' | 'right'): void;
|
|
70
|
+
/** 공개 API(§6.2): source→target 채우기. axis 는 두 rect 의 상대 위치로 추론한다. */
|
|
71
|
+
fillRange(source: CellRange, target: CellRange, mode?: FillMode): void;
|
|
72
|
+
private _isEditable;
|
|
73
|
+
private _commitFill;
|
|
74
|
+
/** KeyboardManager._copyToClipboard 가 소비. 범위 없으면 null(호출측이 기존 경로로 폴백). */
|
|
75
|
+
copyText(): string | null;
|
|
76
|
+
/** KeyboardManager._pasteFromClipboard 가 소비. true = 처리함(배치 경유), false = 범위 없음(폴백). */
|
|
77
|
+
pasteText(text: string): boolean;
|
|
78
|
+
private _maybeAutoscroll;
|
|
79
|
+
private _scrollSpeed;
|
|
80
|
+
private _runAutoscroll;
|
|
81
|
+
private _stopAutoscroll;
|
|
82
|
+
/** bodyWrap 자식으로 오버레이 1회 생성(renderBody 파괴 회피, CON-3 해법). */
|
|
83
|
+
mount(bodyWrap: HTMLElement): void;
|
|
84
|
+
/** _doRender 매 호출 뒤 실행(M-6 통합점) — 코너 셀 실측 → 연속 테두리/핸들/프리뷰 갱신(QA-2, CON-4). */
|
|
85
|
+
repaint(): void;
|
|
86
|
+
private _hideOverlay;
|
|
87
|
+
/** OpenGrid._doRender 가 renderBody extraOpts 로 전달(M-6). */
|
|
88
|
+
getOverlayExtraOpts(): {
|
|
89
|
+
_rangeRects: CellRange[];
|
|
90
|
+
};
|
|
91
|
+
private _resolveCellAtPoint;
|
|
92
|
+
private _onHandlePointerDown;
|
|
93
|
+
private _onHandlePointerMove;
|
|
94
|
+
private _onHandlePointerUp;
|
|
95
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { GridRenderer, DetailRenderContext } from './GridRenderer.js';
|
|
2
|
+
import { VirtualScroll } from './VirtualScroll.js';
|
|
3
|
+
import { Pagination } from './Pagination.js';
|
|
4
|
+
import { ColumnLayout } from './ColumnLayout.js';
|
|
5
|
+
import { DataLayer } from './DataLayer.js';
|
|
6
|
+
import { FlatRowModel } from './FlatRowModel.js';
|
|
7
|
+
import { MergeEngine } from './MergeEngine.js';
|
|
8
|
+
import { SortFilterManager } from './SortFilterManager.js';
|
|
9
|
+
import { RowManager } from './RowManager.js';
|
|
10
|
+
import { CellEditManager } from './CellEditManager.js';
|
|
11
|
+
import { GroupTreeManager } from './GroupTreeManager.js';
|
|
12
|
+
import { DetailManager } from './DetailManager.js';
|
|
13
|
+
import { RangeSelectionManager } from './RangeSelectionManager.js';
|
|
14
|
+
import { GridOptions } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* R5(§3.1 C4, §6-R5): 렌더 루프의 유일 진입점. `OpenGrid` God object 에서
|
|
17
|
+
* `_onResize`/`_recalcWidths`/`_renderHeader`/`_syncHeaderLayout`/`_doRender`/`_visRange`
|
|
18
|
+
* (+ 전용 헬퍼 `_visCount`/`_paginationHeight`)를 **동작 불변**으로 옮긴 것.
|
|
19
|
+
*
|
|
20
|
+
* 스트랭글러 원칙(A2): 협력자(GridRenderer/VirtualScroll/Pagination 등)는 여전히
|
|
21
|
+
* `OpenGrid._mount` 가 생성·소유하며, 여기에는 `*Deps` 클로저 역전 패턴으로 **주입**만 된다.
|
|
22
|
+
* 값(컬럼폭·옵션 등)은 늦은-null / 재할당(worksheet 전환 시 colLayout 교체)을 견디도록
|
|
23
|
+
* 전부 getter 클로저로 읽는다. `fallbackViewportHeight` 클램프 시맨틱과 RenderFrame 구성은
|
|
24
|
+
* 원본과 1:1 동일하다(회귀 0).
|
|
25
|
+
*/
|
|
26
|
+
export interface RenderControllerDeps<T extends Record<string, any> = any> {
|
|
27
|
+
getContainer: () => HTMLElement;
|
|
28
|
+
getOptions: () => Required<GridOptions<T>>;
|
|
29
|
+
getRenderer: () => GridRenderer | null;
|
|
30
|
+
getVs: () => VirtualScroll | null;
|
|
31
|
+
getPagination: () => Pagination | null;
|
|
32
|
+
getData: () => DataLayer<T>;
|
|
33
|
+
getColLayout: () => ColumnLayout<T>;
|
|
34
|
+
getFlatModel: () => FlatRowModel;
|
|
35
|
+
getMergeEngine: () => MergeEngine;
|
|
36
|
+
getColWidths: () => number[];
|
|
37
|
+
setColWidths: (widths: number[]) => void;
|
|
38
|
+
getUserWidths: () => Map<string, number>;
|
|
39
|
+
getSfMgr: () => SortFilterManager<T>;
|
|
40
|
+
getRowMgr: () => RowManager<T>;
|
|
41
|
+
getEditMgr: () => CellEditManager<T>;
|
|
42
|
+
getGrpMgr: () => GroupTreeManager<T>;
|
|
43
|
+
getDetailMgr: () => DetailManager<T>;
|
|
44
|
+
getRangeMgr: () => RangeSelectionManager<T>;
|
|
45
|
+
buildDetailRenderContext: () => DetailRenderContext | undefined;
|
|
46
|
+
renderFooterEl: () => void;
|
|
47
|
+
}
|
|
48
|
+
export declare class RenderController<T extends Record<string, any> = any> {
|
|
49
|
+
private _deps;
|
|
50
|
+
private _autoHeightWarned;
|
|
51
|
+
constructor(deps: RenderControllerDeps<T>);
|
|
52
|
+
private _paginationHeight;
|
|
53
|
+
onResize(): void;
|
|
54
|
+
recalcWidths(totalWidth: number): void;
|
|
55
|
+
renderHeader(): void;
|
|
56
|
+
/**
|
|
57
|
+
* 렌더된 헤더의 실제 높이를 측정해 본문(bodyWrap) 높이와 뷰포트 높이에 반영한다.
|
|
58
|
+
* 줄바꿈이 없는 헤더는 측정 높이가 headerHeight 이하라 기존 고정 동작과 동일하다.
|
|
59
|
+
* (public: OpenGrid 가 `_syncHeaderLayout` 위임으로 노출 — 특성화 테스트가 직접 호출한다.)
|
|
60
|
+
*/
|
|
61
|
+
syncHeaderLayout(): void;
|
|
62
|
+
doRender(startIndex: number, endIndex: number): void;
|
|
63
|
+
visRange(): [number, number];
|
|
64
|
+
private _visCount;
|
|
65
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SkinTokenDelta } from './types.js';
|
|
2
|
+
export interface SkinDefineResult {
|
|
3
|
+
/** 실제 등록된(가드레일 클램프가 반영된) 델타. */
|
|
4
|
+
readonly delta: SkinTokenDelta;
|
|
5
|
+
/** 접근성 가드레일이 조정한 토큰 경고(있으면 콘솔에도 출력). */
|
|
6
|
+
readonly warnings: string[];
|
|
7
|
+
}
|
|
8
|
+
/** 스킨 델타가 색 리터럴을 담고 있는지 검사하고, 위반 시 던진다(FORM-only, Rule 2). */
|
|
9
|
+
export declare function assertFormOnly(id: string, delta: SkinTokenDelta): void;
|
|
10
|
+
/**
|
|
11
|
+
* HANMS 접근성 가드레일(불변식) 적용 — 정의 시점 클램프(§6.4, HANMS P0-4).
|
|
12
|
+
* - focus-width < 2px → 2px 로 클램프(가시 포커스 비협상).
|
|
13
|
+
* - focus-style: none → solid.
|
|
14
|
+
* 반환은 조정된 델타 + 경고 목록(silent override 아님 — 무엇을 클램프했는지 알린다).
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyGuardrails(id: string, delta: SkinTokenDelta): SkinDefineResult;
|
|
17
|
+
/**
|
|
18
|
+
* 프로세스 전역 스킨 등록소. defineSkin(사용자) 는 검증+가드레일+`<style>` 주입,
|
|
19
|
+
* registerBuiltin(내장) 은 검증+가드레일만(CSS 는 skins.css 정적 번들 소유).
|
|
20
|
+
*/
|
|
21
|
+
export declare class SkinRegistry {
|
|
22
|
+
private _skins;
|
|
23
|
+
private _styleEl;
|
|
24
|
+
/** 내장 스킨 등록(주입 없음 — CSS 는 skins.css 가 전달). 검증/가드레일은 동일 적용. */
|
|
25
|
+
registerBuiltin(id: string, delta: SkinTokenDelta): void;
|
|
26
|
+
/**
|
|
27
|
+
* 사용자 스킨 등록. FORM-only 검증 + 가드레일 클램프 후 런타임 `<style>` 로
|
|
28
|
+
* `.og-container[data-og-skin="id"]` 블록을 주입(브라우저 환경). 반환은 조정 결과.
|
|
29
|
+
*/
|
|
30
|
+
define(id: string, delta: SkinTokenDelta): SkinDefineResult;
|
|
31
|
+
has(id: string): boolean;
|
|
32
|
+
get(id: string): SkinTokenDelta | undefined;
|
|
33
|
+
/** 등록된 모든 스킨 id(내장 + 사용자). */
|
|
34
|
+
list(): string[];
|
|
35
|
+
/** 런타임 `<style>` 주입(테스트/SSR 등 document 없으면 no-op). 같은 태그를 누적 사용. */
|
|
36
|
+
private _inject;
|
|
37
|
+
}
|
|
38
|
+
/** Sharp/Gothic — 엔터프라이즈 고밀도·각짐(§3.1). HANMS: APPROVE-WITH-GUARDRAIL(G-S1). */
|
|
39
|
+
export declare const SKIN_SHARP: SkinTokenDelta;
|
|
40
|
+
/** Rounded — 소비자 SaaS 소프트(§3.2). HANMS: APPROVE. */
|
|
41
|
+
export declare const SKIN_ROUNDED: SkinTokenDelta;
|
|
42
|
+
/** Stitch — 핸드크래프트(§3.3). HANMS: APPROVE-WITH-GUARDRAIL(G-ST1~3). 색(리넨/자수)은 theme 축. */
|
|
43
|
+
export declare const SKIN_STITCH: SkinTokenDelta;
|
|
44
|
+
/** Flat/Minimal — 플랫 2.0(§3.5). HANMS: APPROVE-WITH-GUARDRAIL(G-F1: 플로팅 표면 1px 보더). */
|
|
45
|
+
export declare const SKIN_FLAT: SkinTokenDelta;
|
|
46
|
+
/** High-Contrast — 접근성 우선·레퍼런스(§3.6). HANMS: APPROVE(안전 폴백). */
|
|
47
|
+
export declare const SKIN_HIGH_CONTRAST: SkinTokenDelta;
|
|
48
|
+
/** Material/Elevated — Neumorph 대체(HANMS §3): 중간 반경 + 정직한 그림자 엘리베이션. APPROVE. */
|
|
49
|
+
export declare const SKIN_MATERIAL: SkinTokenDelta;
|
|
50
|
+
/** 내장 스킨 카탈로그(HANMS 확정 6종, Neumorph 제외). id → 델타. */
|
|
51
|
+
export declare const BUILTIN_SKINS: ReadonlyArray<readonly [string, SkinTokenDelta]>;
|
|
52
|
+
/** 프로세스 전역 기본 레지스트리 — 내장 스킨을 부트스트랩 등록(주입 없음, CSS=skins.css). */
|
|
53
|
+
export declare const skinRegistry: SkinRegistry;
|
|
@@ -14,6 +14,8 @@ export interface SortFilterDeps<T extends Record<string, any>> {
|
|
|
14
14
|
doRender: () => void;
|
|
15
15
|
announce: (msg: string) => void;
|
|
16
16
|
emit: (event: string, ...args: any[]) => void;
|
|
17
|
+
/** C0.5/§2.5: 정렬/필터 후 F1 범위 선택을 rowId 집합 기준으로 재투영(해제 아님). */
|
|
18
|
+
onReproject?: () => void;
|
|
17
19
|
}
|
|
18
20
|
export declare class SortFilterManager<T extends Record<string, any> = any> {
|
|
19
21
|
private _sortList;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ChartAdapter, ChartDataModel, ChartPoint, ChartRenderSpec } from './types.js';
|
|
2
|
+
import { PointGeom } from './hittest.js';
|
|
3
|
+
export declare class CanvasAdapter implements ChartAdapter {
|
|
4
|
+
readonly id = "builtin-canvas";
|
|
5
|
+
private _host;
|
|
6
|
+
private _canvas;
|
|
7
|
+
private _a11yTable;
|
|
8
|
+
private _legend;
|
|
9
|
+
private _tooltip;
|
|
10
|
+
private _live;
|
|
11
|
+
private _spec;
|
|
12
|
+
private _model;
|
|
13
|
+
private _w;
|
|
14
|
+
private _h;
|
|
15
|
+
private _geoms;
|
|
16
|
+
private _hidden;
|
|
17
|
+
private _cursor;
|
|
18
|
+
private _onPoint;
|
|
19
|
+
init(host: HTMLElement, spec: ChartRenderSpec): Promise<void>;
|
|
20
|
+
render(model: ChartDataModel, spec: ChartRenderSpec): void;
|
|
21
|
+
resize(width: number, height: number): void;
|
|
22
|
+
onPointClick(cb: (p: ChartPoint) => void): void;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
/** 렌더된 포인트 기하(hittest.spec/adapter.spec 검증용). */
|
|
25
|
+
getGeometry(): readonly PointGeom[];
|
|
26
|
+
private _renderA11yTable;
|
|
27
|
+
/**
|
|
28
|
+
* diff 렌더: series 수/이름이 이전과 동일하면 기존 버튼 DOM 을 재사용해 aria-pressed·색·
|
|
29
|
+
* 라벨만 갱신한다(포커스 보존). series 구성 자체가 바뀔 때만 통째로 재생성하되, 재생성 직전
|
|
30
|
+
* activeElement 가 범례 내부 버튼이면 재생성 후 동일 index 버튼에 포커스를 복원한다
|
|
31
|
+
* (코드리뷰 MAJOR: 라이브 재렌더가 범례 innerHTML='' 로 키보드 포커스를 유실하던 문제).
|
|
32
|
+
*/
|
|
33
|
+
private _renderLegend;
|
|
34
|
+
/** 범례 버튼의 aria-pressed/색상 스와치/라벨(패턴 병기)을 현재 상태로 갱신(DOM 은 그대로). */
|
|
35
|
+
private _updateLegendButton;
|
|
36
|
+
private _styles;
|
|
37
|
+
private _plotRect;
|
|
38
|
+
private _valueExtent;
|
|
39
|
+
private _computeGeometry;
|
|
40
|
+
private _paint;
|
|
41
|
+
private _localXY;
|
|
42
|
+
private _onMouseMove;
|
|
43
|
+
private _onMouseLeave;
|
|
44
|
+
private _onClick;
|
|
45
|
+
private _onKeyDown;
|
|
46
|
+
private _cursorPoint;
|
|
47
|
+
private _announceCursor;
|
|
48
|
+
private _pointOf;
|
|
49
|
+
private _emitPoint;
|
|
50
|
+
private _showTooltip;
|
|
51
|
+
private _hideTooltip;
|
|
52
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CellRange } from '../types.js';
|
|
2
|
+
import { ChartAggregate, ChartDataModel, ChartSeriesSpec, ChartSource } from './types.js';
|
|
3
|
+
import { ChartNumberFormat } from './a11y.js';
|
|
4
|
+
/** ColumnLayout.visibleLeaves 의 최소 투영(field/header/type 만 필요, C0.4). */
|
|
5
|
+
export interface ChartColumnRef {
|
|
6
|
+
field: string;
|
|
7
|
+
header?: string | undefined;
|
|
8
|
+
type?: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface ChartExtractDeps {
|
|
11
|
+
/** getData() 전체(display 순서) — kind='all'|'columns' */
|
|
12
|
+
getAllRows(): Array<Record<string, any>>;
|
|
13
|
+
/** getSelections() — kind='selection' */
|
|
14
|
+
getSelectedRows(): Array<Record<string, any>>;
|
|
15
|
+
/** getChecked() 의 row 부분 — kind='checked' */
|
|
16
|
+
getCheckedRows(): Array<Record<string, any>>;
|
|
17
|
+
/** ColumnLayout.visibleLeaves 투영(숨김 제외, C0.4) */
|
|
18
|
+
getVisibleColumns(): ChartColumnRef[];
|
|
19
|
+
/**
|
|
20
|
+
* kind='range' 전용: 스냅샷/현재 range 에 대응하는 행 배열(FlatRowModel 로 이미
|
|
21
|
+
* pseudo-row 를 제외한 상태, C0.3). 부재 시 range 소스는 selection 으로 강등한다(§7).
|
|
22
|
+
*/
|
|
23
|
+
getRangeRows?: ((range: CellRange) => Array<Record<string, any>>) | undefined;
|
|
24
|
+
/** kind='range' 전용: range.startCol..endCol 에 대응하는 visibleLeaves 서브셋(C0.4). */
|
|
25
|
+
getRangeColumns?: ((range: CellRange) => ChartColumnRef[]) | undefined;
|
|
26
|
+
/** range 생략 시 초기값 취득(C4). 없거나 null 이면 selection 으로 강등(§7). */
|
|
27
|
+
getActiveRange?: (() => CellRange | null) | undefined;
|
|
28
|
+
}
|
|
29
|
+
export interface ChartExtractConfig {
|
|
30
|
+
/** 축 카테고리 컬럼 override(FR-2). 미지정 시 §2.2 자동 추론. */
|
|
31
|
+
category?: string | undefined;
|
|
32
|
+
/** 시리즈 컬럼 override(FR-2). 'columns' 소스는 필수(source.series 로도 지정 가능). */
|
|
33
|
+
series?: Array<string | ChartSeriesSpec> | undefined;
|
|
34
|
+
/** 동일 category 중복 시 축약(FR-3). 미지정 시 중복 category 를 그대로 유지(비집계). */
|
|
35
|
+
aggregate?: ChartAggregate | undefined;
|
|
36
|
+
title?: string | undefined;
|
|
37
|
+
numberFormat?: ChartNumberFormat | undefined;
|
|
38
|
+
}
|
|
39
|
+
/** 소스 강등 없이 실제로 사용된 소스 종류(§7 fallback 반영, 배지 판단에 쓰라고 반환). */
|
|
40
|
+
export interface ChartExtractResult {
|
|
41
|
+
model: ChartDataModel;
|
|
42
|
+
/** true 면 kind='range' 요청이 selection 으로 강등됐다(F1 부재/range 미해소, §7 HANMS-04). */
|
|
43
|
+
rangeFallback: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 소스(§2.1)로부터 `ChartDataModel`을 산출한다(FR-1: 4소스 → 동형 모델).
|
|
47
|
+
* `meta.a11yTable`은 항상 채운다(§B 하드 게이트, "생성비용 0" 미러).
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractChartData(source: ChartSource, deps: ChartExtractDeps, config?: ChartExtractConfig): ChartExtractResult;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChartDataModel, A11yTableModel } from './types.js';
|
|
2
|
+
export type ChartNumberFormat = (v: number, ctx: {
|
|
3
|
+
axis: 'x' | 'y' | 'tooltip' | 'legend';
|
|
4
|
+
field?: string;
|
|
5
|
+
}) => string;
|
|
6
|
+
export interface BuildA11yTableOptions {
|
|
7
|
+
title?: string | undefined;
|
|
8
|
+
numberFormat?: ChartNumberFormat | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* `ChartDataModel`(categories/series 부분)을 시각숨김 `<table>` 미러 데이터로 변환한다(§B.1).
|
|
12
|
+
* - colHeaders: ['category', ...series names]
|
|
13
|
+
* - rows: [category, v1, v2, ...] (locale 포맷 문자열, 결측=빈 문자열)
|
|
14
|
+
* - caption: 요약 — 카테고리 수·시리즈명 나열(스크린리더가 표 진입 전 듣는 개요).
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildA11yTable(model: Pick<ChartDataModel, 'categories' | 'series'>, opts?: BuildA11yTableOptions): A11yTableModel;
|
|
17
|
+
/**
|
|
18
|
+
* `<canvas role="img" aria-label="...">` 에 쓸 요약 문자열(§B.1).
|
|
19
|
+
* "{title}: {category}별 {series} — {요약}" 형태. 상세 값은 형제 `<table>`(aria-describedby)로.
|
|
20
|
+
*/
|
|
21
|
+
export declare function chartAriaLabel(model: Pick<ChartDataModel, 'categories' | 'series'>, title?: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ChartDataModel, ChartType } from './types.js';
|
|
2
|
+
import { ChartNumberFormat } from './a11y.js';
|
|
3
|
+
/**
|
|
4
|
+
* LTTB 코어 — x(=category index 0..n-1)·y(대표값) 에서 threshold 개 인덱스를 고른다.
|
|
5
|
+
* 항상 첫/마지막을 포함한다. threshold>=n 이면 전 인덱스 반환.
|
|
6
|
+
*/
|
|
7
|
+
export declare function lttbIndices(y: Array<number | null>, threshold: number): number[];
|
|
8
|
+
export interface DownsampleResult {
|
|
9
|
+
model: ChartDataModel;
|
|
10
|
+
/** true 면 축약이 일어났다(배지 §C). */
|
|
11
|
+
sampled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface DownsampleOptions {
|
|
14
|
+
title?: string | undefined;
|
|
15
|
+
numberFormat?: ChartNumberFormat | undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `ChartDataModel`을 maxPoints 이하로 축약한다(§8.2). categories/series 를 함께 줄여
|
|
19
|
+
* 정합을 유지하고, meta.sampled/sampledFrom/sampledTo 를 채운다(배지 §C). a11yTable 은
|
|
20
|
+
* 축약된 데이터로 재생성해 모델 자기정합을 유지한다(§B.4: 셀 수 == categories×(series+1)).
|
|
21
|
+
*
|
|
22
|
+
* - line/area: 공유 인덱스 LTTB + 각 series 엔벨로프(argmin/argmax) 강제 포함 → 극값 정확 보존.
|
|
23
|
+
* - 그 외(bar): 인접 category 를 균등 버킷으로 묶어 대표(첫 category 라벨) + 값 합산.
|
|
24
|
+
*/
|
|
25
|
+
export declare function downsampleModel(model: ChartDataModel, maxPoints: number, type: ChartType, opts?: DownsampleOptions): DownsampleResult;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChartType } from './types.js';
|
|
2
|
+
/** 렌더된 데이터포인트 하나의 기하. bar=사각형(x,y,w,h), line/marker=중심(cx,cy). */
|
|
3
|
+
export interface PointGeom {
|
|
4
|
+
seriesIndex: number;
|
|
5
|
+
categoryIndex: number;
|
|
6
|
+
/** 사각형 좌상단(bar). line 은 마커 bbox 좌상단으로도 채울 수 있다. */
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
w: number;
|
|
10
|
+
h: number;
|
|
11
|
+
/** 중심 좌표(line 마커 최근접용, bar 도 중심 계산해 채운다). */
|
|
12
|
+
cx: number;
|
|
13
|
+
cy: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 포인터 좌표(px,py)에 해당하는 데이터포인트 기하를 찾는다(§8.3).
|
|
17
|
+
* - bar/bar-*: 사각형 contains(미스면 null → 툴팁 숨김).
|
|
18
|
+
* - line/area: 최근접 x → 최근접 y(항상 하나 반환, 미스 개념 없음).
|
|
19
|
+
*/
|
|
20
|
+
export declare function hitTest(geoms: readonly PointGeom[], px: number, py: number, type: ChartType): PointGeom | null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ChartSeries } from './types.js';
|
|
2
|
+
/** Okabe-Ito 8색(색약 안전 세트) — 배치 순서는 인접 대비≥3:1이 되도록 §D에 맞춰 조정. */
|
|
3
|
+
export declare const OKABE_ITO: readonly string[];
|
|
4
|
+
/** 색 외 구분(§D): series 인덱스 순환 배정. bar=텍스처, line=대시+마커에 대응. */
|
|
5
|
+
export declare const PATTERN_CYCLE: ReadonlyArray<NonNullable<ChartSeries['pattern']>>;
|
|
6
|
+
export interface Rgb {
|
|
7
|
+
r: number;
|
|
8
|
+
g: number;
|
|
9
|
+
b: number;
|
|
10
|
+
}
|
|
11
|
+
/** '#rgb'/'#rrggbb'/'rgb(a)()' → RGB(0-255). 실패 시 null. */
|
|
12
|
+
export declare function parseColor(input: string): Rgb | null;
|
|
13
|
+
/** 'rgba(r, g, b, 1)' 정규화 문자열 — UR-2 theme_bind 비교용(§1). */
|
|
14
|
+
export declare function normalizeColor(input: string): string | null;
|
|
15
|
+
/** WCAG relative luminance (0..1). */
|
|
16
|
+
export declare function relativeLuminance(c: Rgb): number;
|
|
17
|
+
/** WCAG 대비비 (1..21). 파싱 실패 색은 1로 취급. */
|
|
18
|
+
export declare function contrastRatio(a: string, b: string): number;
|
|
19
|
+
export type Dichromacy = 'deuteranopia' | 'protanopia';
|
|
20
|
+
/** 색약 변환 시뮬레이션 — RGB in/out(0-255). */
|
|
21
|
+
export declare function simulateDichromacy(c: Rgb, kind: Dichromacy): Rgb;
|
|
22
|
+
/** 단순 유클리드 RGB 거리(ΔE 근사, 0..441). palette.spec 임계 비교용. */
|
|
23
|
+
export declare function colorDistance(a: Rgb, b: Rgb): number;
|
|
24
|
+
/**
|
|
25
|
+
* 인접 대비를 **최대화**하도록 팔레트를 그리디 재배치한다(§D "미달 시 팔레트 재배치").
|
|
26
|
+
* 첫 색에서 시작해 매번 직전 색과 대비가 가장 큰 색을 이어붙인다(O(n²), 결정론적).
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ 정직한 한계(설계 갱신 필요): 8색 색약안전 팔레트는 **어떤 순열로도** 인접 luminance
|
|
29
|
+
* 대비 ≥3:1 을 전부 만족할 수 없다(수학적 상한 ≈1.52, 브루트포스 확인). WCAG 3:1 은 본디
|
|
30
|
+
* 전경-배경(텍스트/UI) 기준이지 인접 카테고리 기준이 아니다. 색약 구별의 실보증은 (1) 색약
|
|
31
|
+
* 시뮬 ΔE 분리(§simulateDichromacy, 인접 최소 ≈78)와 (2) 색 외 중복 부호화(패턴/대시/마커,
|
|
32
|
+
* PATTERN_CYCLE)에 있다. 본 함수는 대비를 "가능한 만큼" 키우는 best-effort 재배치다.
|
|
33
|
+
*/
|
|
34
|
+
export declare function orderByAdjacentContrast(colors: readonly string[]): string[];
|
|
35
|
+
/** 인접 색쌍의 최소 대비비(테스트/재배치 판정용). */
|
|
36
|
+
export declare function minAdjacentContrast(colors: readonly string[]): number;
|
|
37
|
+
/** 인접 색쌍의 색약 시뮬 ΔE 최소값(deuteranopia/protanopia 중 나쁜 쪽). 색약 구별 실보증. */
|
|
38
|
+
export declare function minAdjacentDichromacyDeltaE(colors: readonly string[]): number;
|
|
39
|
+
export interface ResolvedSeriesStyle {
|
|
40
|
+
color: string;
|
|
41
|
+
pattern: NonNullable<ChartSeries['pattern']>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* series 별 색/패턴을 결정한다(§D).
|
|
45
|
+
* - series.color 명시가 최우선.
|
|
46
|
+
* - primary(테마 --og-primary)가 주어지면 첫 팔레트 색으로 유도하되, 다음 색과의
|
|
47
|
+
* 대비가 3:1 미달이면 안전 팔레트 원본을 그대로 쓴다(§D "fallback으로만").
|
|
48
|
+
* - 패턴은 인덱스 순환(유일성은 series≤4에서 보장, 초과 시 색+패턴 조합으로 구분).
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveSeriesStyles(series: ReadonlyArray<{
|
|
51
|
+
color?: string | undefined;
|
|
52
|
+
pattern?: ChartSeries['pattern'] | undefined;
|
|
53
|
+
}>, opts?: {
|
|
54
|
+
palette?: readonly string[] | undefined;
|
|
55
|
+
primary?: string | undefined;
|
|
56
|
+
}): ResolvedSeriesStyle[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F4 — nice-number 축 눈금 스케일(순수 함수, 헤드리스). §8.1(자동검증 대상 수학).
|
|
3
|
+
*
|
|
4
|
+
* 표준 Heckbert "Nice Numbers for Graph Labels" 알고리즘. 목표 tick 수(default 6)에 맞춰
|
|
5
|
+
* step 을 1/2/5×10^n 중에서 선택하고, [min,max] 를 그 step 배수로 확장한다.
|
|
6
|
+
*
|
|
7
|
+
* 한계(정직 명시): 이 알고리즘은 min=0 류의 "원점 기준" 범위에서는 매우 안정적으로
|
|
8
|
+
* tick 5~6개를 낸다(설계서 §8.1 문서화 예시 [0,97]→6 tick 포함). min≠0 인 임의 구간에서는
|
|
9
|
+
* step 후보가 {1,2,5,10} 로 성기어(coarse) tick 수가 4개나 7개로 튈 수 있다 — 표준 알고리즘의
|
|
10
|
+
* 알려진 한계이며, 본 구현은 문서화된 대표 입력(§8.1)에 대해서만 5~6 불변식을 보장한다.
|
|
11
|
+
*/
|
|
12
|
+
export interface NiceScale {
|
|
13
|
+
min: number;
|
|
14
|
+
max: number;
|
|
15
|
+
step: number;
|
|
16
|
+
ticks: number[];
|
|
17
|
+
}
|
|
18
|
+
/** range 를 1/2/5×10^n 중 하나로 반올림한다(round=true: 가장 가까운 값, false: 올림 쪽 느슨한 값). */
|
|
19
|
+
export declare function niceNum(range: number, round: boolean): number;
|
|
20
|
+
/**
|
|
21
|
+
* [dataMin,dataMax] → nice range/step/tick 배열(§8.1). maxTicks 는 목표 tick 수(default 6).
|
|
22
|
+
* dataMin===dataMax(degenerate) 이면 값 주변으로 인위 확장한다.
|
|
23
|
+
*/
|
|
24
|
+
export declare function niceScale(dataMin: number, dataMax: number, maxTicks?: number): NiceScale;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { CellRange } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Phase1 MVP = 'bar'|'line'. 나머지는 Phase2/3 예약(타입만 선언, 미구현).
|
|
4
|
+
*
|
|
5
|
+
* ⚠️ 'bar-stacked': 공개 타입으로 노출되어 있으나 내장(builtin-canvas) 렌더러는 현재 스택
|
|
6
|
+
* 누적을 구현하지 않는다 — 지정해도 'bar-grouped'와 동일하게 그룹형(side-by-side)으로
|
|
7
|
+
* 폴백 렌더된다(CanvasAdapter._computeGeometry). 하위호환을 위해 타입 자체는 유지한다.
|
|
8
|
+
*/
|
|
9
|
+
export type ChartType = 'bar' | 'line' | 'area' | 'pie' | 'doughnut' | 'bar-stacked' | 'bar-grouped';
|
|
10
|
+
export interface ChartSeriesSpec {
|
|
11
|
+
field: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
color?: string;
|
|
14
|
+
pattern?: ChartSeries['pattern'];
|
|
15
|
+
type?: 'bar' | 'line' | 'area';
|
|
16
|
+
}
|
|
17
|
+
export type ChartSource = {
|
|
18
|
+
kind: 'range';
|
|
19
|
+
range?: CellRange;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'selection';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'checked';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'all';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'columns';
|
|
28
|
+
category?: string;
|
|
29
|
+
series: Array<string | ChartSeriesSpec>;
|
|
30
|
+
};
|
|
31
|
+
export type ChartAggregateOp = 'sum' | 'avg' | 'count' | 'min' | 'max';
|
|
32
|
+
export type ChartAggregate = ChartAggregateOp | ((values: number[], category: string) => number);
|
|
33
|
+
export interface A11yTableModel {
|
|
34
|
+
/** aria-label 요약 캡션 */
|
|
35
|
+
caption: string;
|
|
36
|
+
/** ['category', ...series names] */
|
|
37
|
+
colHeaders: string[];
|
|
38
|
+
/** [category, v1, v2, ...] — locale 포맷 문자열 */
|
|
39
|
+
rows: string[][];
|
|
40
|
+
}
|
|
41
|
+
export interface ChartSeries {
|
|
42
|
+
/** 범례 라벨(기본값 = 원본 컬럼 header/field) */
|
|
43
|
+
name: string;
|
|
44
|
+
/** categories 와 동일 순서로 정렬. 결측=null */
|
|
45
|
+
data: Array<number | null>;
|
|
46
|
+
color?: string;
|
|
47
|
+
/** 색 외 구분(HANMS-19) */
|
|
48
|
+
pattern?: 'solid' | 'hatch' | 'dot' | 'cross';
|
|
49
|
+
}
|
|
50
|
+
export interface ChartDataModelMeta {
|
|
51
|
+
sourceKind: ChartSource['kind'];
|
|
52
|
+
/** 원본 포인트(행) 수 */
|
|
53
|
+
total: number;
|
|
54
|
+
/** LTTB 다운샘플 또는 category 집계로 축약됐는가 → 배지(§C) */
|
|
55
|
+
sampled: boolean;
|
|
56
|
+
sampledFrom?: number;
|
|
57
|
+
sampledTo?: number;
|
|
58
|
+
aggregatedOp?: 'sum' | 'avg' | 'count' | 'min' | 'max' | 'custom';
|
|
59
|
+
pieReducedToFirst?: boolean;
|
|
60
|
+
negativesAbsInPie?: boolean;
|
|
61
|
+
/** SR 폴백 — extractor 가 렌더러와 무관하게 항상 채운다(§B 하드 게이트) */
|
|
62
|
+
a11yTable: A11yTableModel;
|
|
63
|
+
}
|
|
64
|
+
export interface ChartDataModel {
|
|
65
|
+
categories: string[];
|
|
66
|
+
series: ChartSeries[];
|
|
67
|
+
meta: ChartDataModelMeta;
|
|
68
|
+
}
|
|
69
|
+
export interface ChartTheme {
|
|
70
|
+
primary: string;
|
|
71
|
+
border: string;
|
|
72
|
+
text: string;
|
|
73
|
+
bg: string;
|
|
74
|
+
gridLine: string;
|
|
75
|
+
fontFamily: string;
|
|
76
|
+
fontSize: number;
|
|
77
|
+
palette: string[];
|
|
78
|
+
}
|
|
79
|
+
export interface ChartRenderSpec {
|
|
80
|
+
type: ChartType;
|
|
81
|
+
title?: string;
|
|
82
|
+
legend?: boolean | {
|
|
83
|
+
position: 'top' | 'bottom' | 'left' | 'right';
|
|
84
|
+
};
|
|
85
|
+
tooltip?: boolean;
|
|
86
|
+
axis?: {
|
|
87
|
+
xLabel?: string;
|
|
88
|
+
yLabel?: string;
|
|
89
|
+
yMin?: number;
|
|
90
|
+
yMax?: number;
|
|
91
|
+
stacked?: boolean;
|
|
92
|
+
};
|
|
93
|
+
palette?: string[];
|
|
94
|
+
theme: ChartTheme;
|
|
95
|
+
numberFormat?: (v: number, ctx: {
|
|
96
|
+
axis: 'x' | 'y' | 'tooltip' | 'legend';
|
|
97
|
+
field?: string;
|
|
98
|
+
}) => string;
|
|
99
|
+
a11y: A11yTableModel;
|
|
100
|
+
}
|
|
101
|
+
export interface ChartPoint {
|
|
102
|
+
seriesName: string;
|
|
103
|
+
category: string;
|
|
104
|
+
value: number | null;
|
|
105
|
+
index: number;
|
|
106
|
+
rowId?: string;
|
|
107
|
+
}
|
|
108
|
+
export interface ChartAdapter {
|
|
109
|
+
readonly id: string;
|
|
110
|
+
init(host: HTMLElement, spec: ChartRenderSpec): Promise<void>;
|
|
111
|
+
render(model: ChartDataModel, spec: ChartRenderSpec): void;
|
|
112
|
+
resize(width: number, height: number): void;
|
|
113
|
+
toBlob?(mime?: string): Promise<Blob | null>;
|
|
114
|
+
onPointClick?(cb: (p: ChartPoint) => void): void;
|
|
115
|
+
destroy(): void;
|
|
116
|
+
}
|
|
117
|
+
/** createChart 반환 핸들(§6). 구현은 ChartManager. */
|
|
118
|
+
export interface ChartInstance {
|
|
119
|
+
readonly id: string;
|
|
120
|
+
update(patch?: Partial<ChartConfig>): void;
|
|
121
|
+
/**
|
|
122
|
+
* 모델을 재추출하고 렌더 스펙(테마 포함)을 재스냅샷해 재렌더한다(§5.3). 그리드는 테마 변경
|
|
123
|
+
* 이벤트를 발행하지 않으므로(`setTheme`/`setThemeVar`는 CSS 만 갱신) 다크모드 토글처럼 데이터
|
|
124
|
+
* 변화 없는 순수 테마 전환 후에는, 열려 있는 각 차트에 대해 이 메서드를 호출해야 새 테마
|
|
125
|
+
* (색·글꼴·팔레트)가 재적용된다. `update()`/`setType()`도 내부적으로 동일 경로를 탄다.
|
|
126
|
+
*/
|
|
127
|
+
refresh(): void;
|
|
128
|
+
setType(type: ChartType): void;
|
|
129
|
+
destroy(): void;
|
|
130
|
+
toBlob(mime?: string): Promise<Blob | null>;
|
|
131
|
+
getModel(): ChartDataModel;
|
|
132
|
+
on(ev: 'chartRender' | 'chartPointClick', cb: (...a: any[]) => void): void;
|
|
133
|
+
}
|
|
134
|
+
/** GridOptions.chart 로 중첩되는 전역 옵션(C5.1, 최상위 flat 키 금지). */
|
|
135
|
+
export interface ChartGlobalOptions {
|
|
136
|
+
enabled?: boolean;
|
|
137
|
+
defaultEngine?: 'builtin' | 'chartjs' | 'echarts';
|
|
138
|
+
defaultType?: ChartType;
|
|
139
|
+
placement?: 'docked' | 'modal' | 'inline' | 'floating';
|
|
140
|
+
maxPoints?: number;
|
|
141
|
+
debounceMs?: number;
|
|
142
|
+
palette?: string[];
|
|
143
|
+
numberFormat?: (v: number, ctx: {
|
|
144
|
+
axis: 'x' | 'y' | 'tooltip' | 'legend';
|
|
145
|
+
field?: string;
|
|
146
|
+
}) => string;
|
|
147
|
+
onChartCreate?: (i: ChartInstance) => void;
|
|
148
|
+
onChartRender?: (e: {
|
|
149
|
+
id: string;
|
|
150
|
+
model: ChartDataModel;
|
|
151
|
+
}) => void;
|
|
152
|
+
onChartPointClick?: (e: {
|
|
153
|
+
id: string;
|
|
154
|
+
point: ChartPoint;
|
|
155
|
+
}) => void;
|
|
156
|
+
onChartDestroy?: (e: {
|
|
157
|
+
id: string;
|
|
158
|
+
}) => void;
|
|
159
|
+
}
|
|
160
|
+
export interface ChartConfig {
|
|
161
|
+
source: ChartSource;
|
|
162
|
+
type: ChartType;
|
|
163
|
+
engine?: 'builtin' | 'chartjs' | 'echarts' | ChartAdapter;
|
|
164
|
+
placement?: 'docked' | 'modal' | 'inline' | 'floating';
|
|
165
|
+
mount?: HTMLElement;
|
|
166
|
+
category?: string;
|
|
167
|
+
series?: Array<string | ChartSeriesSpec>;
|
|
168
|
+
aggregate?: ChartAggregate;
|
|
169
|
+
maxPoints?: number;
|
|
170
|
+
live?: boolean;
|
|
171
|
+
title?: string;
|
|
172
|
+
legend?: ChartRenderSpec['legend'];
|
|
173
|
+
tooltip?: boolean;
|
|
174
|
+
axis?: ChartRenderSpec['axis'];
|
|
175
|
+
palette?: string[];
|
|
176
|
+
numberFormat?: ChartRenderSpec['numberFormat'];
|
|
177
|
+
size?: {
|
|
178
|
+
width: number;
|
|
179
|
+
height: number;
|
|
180
|
+
};
|
|
181
|
+
}
|