@threestarsoftware/tssgrid 0.0.8 → 0.0.9

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/src/tssgrid.d.ts CHANGED
@@ -1,348 +1,380 @@
1
- // =============================================================================
2
- // TssGrid 型定義(公開APIの契約)
3
- // - これが「外から呼べるもの」の正本。エディタ補完にはここに宣言したものだけ出る
4
- // =内部メソッド(setCell / pushCmd / place など)は候補に出ず、自然に守られる。
5
- // - 低レベルだが公開しているメソッドは JSDoc に「通常は○○を推奨」と明記(逃げ道は塞がない)。
6
- // - v1 ドラフト。実装と差異を見つけたら本ファイルを正として揃える/直す。
7
- // - 使い方:
8
- // <script src="tssgrid.js"> 読み込み時 … グローバル TssGrid / HistoryManager に型が付く
9
- // import { TssGrid } from 'tssgrid' … ESM entry 整備後(§npm化)に有効
10
- // =============================================================================
11
-
12
- export type MoveDir = 'down' | 'up' | 'right' | 'left' | 'none';
13
- export type CellType = 'text' | 'number' | 'date' | 'time' | 'dropdown' | 'checkbox';
14
- export type ChangeSource = 'edit' | 'paste' | 'fill' | 'delete' | 'undo' | 'redo';
15
-
16
- /** 1つの値変更(onBeforeChange / onAfterChange の配列要素)。newValue を書き換えると整形確定。 */
17
- export interface ChangeItem {
18
- r: number;
19
- c: number;
20
- oldValue: any;
21
- newValue: any;
22
- source: ChangeSource;
23
- }
24
-
25
- /** 選択範囲。r0/c0=開始、r1/c1=終了(昇順とは限らない)。 */
26
- export interface SelectionRange { r0: number; c0: number; r1: number; c1: number; }
27
- export interface CellCoord { r: number; c: number; }
28
- export interface SelectionInfo { range: SelectionRange; active: CellCoord; extent: CellCoord; }
29
-
30
- /** validator が弾いたセル(onInvalid / getInvalidCells)。 */
31
- export interface Rejection { r: number; c: number; value: any; code?: string; level?: string; message?: string; }
32
- /** 読み取り専用セルへの変更を弾いた時(onReadOnly)。 */
33
- export interface ReadOnlyBlock { r: number; c: number; value: any; }
34
-
35
- /** 行/列の挿入・削除の情報(onStructureChange / onBeforeStructureChange)。 */
36
- export interface StructureInfo { type: 'insertRow' | 'deleteRows' | 'insertCol' | 'deleteCols'; undo?: boolean; [k: string]: any; }
37
-
38
- /** validator の戻り値: true=OK / 文字列=エラー文 / オブジェクト=メッセージカタログ解決用。 */
39
- export type ValidatorResult = true | string | { code: string; params?: Record<string, any>; level?: string };
40
-
41
- /** 列定義(options.columns[c])。`data` は data オブジェクトのキー(または列 index)。 */
42
- export interface ColumnDef {
43
- /** data オブジェクトのキー。配列データなら省略可(位置で対応)。 */
44
- data?: string | number;
45
- /** ヘッダ見出し(headers より優先)。 */
46
- title?: string;
47
- /** セルタイプ。既定 'text'。 */
48
- type?: CellType;
49
- /** dropdown の選択肢。 */
50
- options?: Array<string | { value: string; label?: string }>;
51
- /** 列ごとの初期幅(px)。列定義に同居=並べ替え/コピペで幅が追従。 */
52
- width?: number;
53
- /** false でこの列だけリサイズ禁止。 */
54
- resizable?: boolean;
55
- /** 列既定の水平/垂直整列。 */
56
- align?: 'left' | 'center' | 'right';
57
- valign?: 'top' | 'middle' | 'bottom';
58
- /** 列単位の読み取り専用。関数でセル単位判定も可。 */
59
- readOnly?: boolean | ((value: any, cell: CellCoord) => boolean);
60
- /** 入力検証。編集/貼付/フィルの全経路に効く。 */
61
- validator?: (value: any, cell: CellCoord) => ValidatorResult;
62
- /** カスタム編集UI(薄いオブジェクト契約 or それを返す関数)。 */
63
- editor?: object | (() => object);
64
- /** 入力の正規化(保存値へ変換)。 */
65
- parse?: (input: string, cell: CellCoord) => any;
66
- /** 表示の整形(保存値→表示)。文字列 or 宣言的 CellFormat。 */
67
- format?: string | object | ((value: any, cell: CellCoord) => string);
68
- /** 数値型: 千区切り表示。 */
69
- thousands?: boolean;
70
- /** 数値型: 接頭辞(例 '¥')。 */
71
- prefix?: string;
72
- /** 値/行を見てセルに付与する CSS クラス(条件付き書式)。 */
73
- cellClass?: (r: number, c: number, value: any, row: any) => string;
74
- /** セル単位のインラインスタイル(連続色・データバー等)。 */
75
- cellStyle?: (r: number, c: number, value: any, row: any) => Partial<CSSStyleDeclaration> | Record<string, string>;
76
- /** true で表示だけ生HTML(値はテキスト保存のまま)。 */
77
- html?: boolean;
78
- /** 列単位の折り返し。 */
79
- wordWrap?: boolean;
80
- /** 複数行(改行)入力を有効化。編集は隠し textarea(IME 直打ち対応)、表示は改行保持(pre-wrap)。行高は自動で伸びないので rowHeights 等で確保する。 */
81
- multiline?: boolean;
82
- /** 空セルの薄いヒント文字。 */
83
- placeholder?: string;
84
- [k: string]: any;
85
- }
86
-
87
- /** new TssGrid(container, options) のオプション。 */
88
- export interface TssGridOptions {
89
- headers?: string[];
90
- /** 初期データ。2次元配列 or オブジェクト配列。 */
91
- data?: any[][] | Record<string, any>[];
92
- /** 渡すと複数グリッドで Undo を共有。 */
93
- history?: HistoryManager;
94
- name?: string;
95
- showDump?: boolean;
96
- /** Enter 確定後の移動方向(既定 'down')。Shift で逆。実行時に書換可。 */
97
- enterMoves?: MoveDir;
98
- /** Tab 確定後の移動方向(既定 'right')。Shift で逆。実行時に書換可。 */
99
- tabMoves?: MoveDir;
100
- initialCell?: [number, number] | { r: number; c: number | string };
101
- /** 入力フロー制御。Enter/Tab の移動先を上書き(null で既定方向)。入力セルだけ巡回できる。 */
102
- nextCell?: (a: { r: number; c: number; key: string; shift: boolean }) => { r: number; c: number } | null;
103
- columns?: ColumnDef[];
104
- /** 検証NG時。'revert'=元に戻す / 'keep'=赤く警告して残す。 */
105
- invalidMode?: 'revert' | 'keep';
106
- invalidTitle?: boolean;
107
- /** エラーの共通メッセージカタログ。 */
108
- messages?: Record<string, any> | ((info: { code: string; params?: any; level?: string }) => string);
109
- pasteOverflow?: 'clip' | 'error';
110
- colWidths?: number[] | Record<string, number>;
111
- rowHeights?: number[] | Record<string, number>;
112
- defaultColWidth?: number;
113
- defaultRowHeight?: number;
114
- minColWidth?: number;
115
- minRowHeight?: number;
116
- resizeMode?: 'preview' | 'live';
117
- /** 左から固定する列数。freezeCols(n) でも変更可。 */
118
- frozenCols?: number;
119
- /** 上から固定する行数。freezeRows(n) でも変更可。frozenCols 併用で四隅固定。 */
120
- frozenRows?: number;
121
- /** ヘッダ結合(複数段見出し)。最下段がリーフ=実列。 */
122
- nestedHeaders?: Array<Array<string | { label: string; colspan?: number }>>;
123
- width?: number | string;
124
- height?: number | string;
125
- resizeCols?: boolean;
126
- resizeRows?: boolean;
127
- /** false で選択カーソルを非表示(表示専用グリッド向け・内部選択は保持)。 */
128
- cursor?: boolean;
129
- stretchH?: 'none' | 'last' | 'all';
130
- rowHeaders?: boolean;
131
- /** 行番号列の幅(px)。既定 40。大量行で桁数が増える時に広げる。 */
132
- rowHeaderWidth?: number;
133
- /** 行ヘッダの表示内容。未指定=行番号(r+1) / false=数字なし(空) / (r)=>文字列=カスタム表示。 */
134
- rowHeaderLabel?: false | ((r: number) => string | number);
135
- /** 行のドラッグ並べ替え。true=行ヘッダーセルの ⠿ アイコンを掴んで移動 / 'header'=行ヘッダーセル全体が移動ハンドル(クリック=選択/ドラッグ=移動)。 */
136
- rowReorder?: boolean | 'header';
137
- /** 行ヘッダーの ⠿ マークの位置。'before'=番号の前(既定)/ 'after'=番号の後 / false=マークを出さない。 */
138
- rowReorderMark?: 'before' | 'after' | false;
139
- /** 仮想スクロール(固定行高ウィンドウイング)。大量行を可視窓だけ描画。true か { buffer:窓上下バッファ行数(既定6) }。
140
- * 制約(v1): 行高一定/固定行列・折り返し・セル結合は非対応(指定時は自動無効化)。 */
141
- virtual?: boolean | { buffer?: number };
142
- colHeaders?: boolean;
143
- hiddenColumns?: number[];
144
- wordWrap?: boolean;
145
- /** multiline 列の Enter 挙動。'commit'(既定・Excel風): Enter=確定 / Alt+Enter=改行。'newline'(メモ帳風): Enter=改行 / Ctrl+Enter=確定。 */
146
- multilineEnter?: 'commit' | 'newline';
147
- /** multiline セル右上の「複数行」ヒント表示(既定 true)。色は CSS 変数 --tg-ml-mark。false で非表示。 */
148
- multilineMark?: boolean;
149
- /** multiline 編集時に伸びる箱の最大行数(既定 10)。超えた分はボックス内スクロール。ビューポート/wrap を超える時はそちらが優先。 */
150
- multilineEditMaxLines?: number;
151
- placeholder?: string;
152
- className?: string;
153
- /** false でフィル完全OFF。詳細指定も可。 */
154
- fillHandle?: boolean | { direction?: 'vertical' | 'horizontal' | 'both'; autoInsertRow?: boolean };
155
- autoColumnSize?: boolean | number;
156
- copyPaste?: boolean;
157
- minSpareRows?: number;
158
- autoWrapRow?: boolean;
159
- autoWrapCol?: boolean;
160
- minRows?: number;
161
- maxRows?: number;
162
- minCols?: number;
163
- maxCols?: number;
164
- /** グリッド全体を読み取り専用(ビューア用途)。 */
165
- readOnly?: boolean;
166
- contextMenu?: boolean | any[] | { items: any[] };
167
- allowInsertRows?: boolean;
168
- allowDeleteRows?: boolean;
169
- allowInsertCols?: boolean;
170
- allowDeleteCols?: boolean;
171
- shortcuts?: any[];
172
- /** プラグイン(関数 or 登録名)。init(grid) で初期化。 */
173
- plugins?: any[];
174
-
175
- // ---- イベント / コールバック -------------------------------------------
176
- /** 確定の直前。検証・自動整形。false で全取消、change.newValue 書換で整形。 */
177
- onBeforeChange?: (changes: ChangeItem[], source: ChangeSource) => boolean | void;
178
- /** 確定の直後(undo/redo 含む)。保存・再計算に。 */
179
- onAfterChange?: (changes: ChangeItem[], source: ChangeSource) => void;
180
- onEditStart?: (info: { r: number; c: number; value: any }) => void;
181
- onEditEnd?: (info: { r: number; c: number; oldValue: any; newValue: any; canceled: boolean }) => void;
182
- onSelectionChange?: (info: SelectionInfo) => void;
183
- onBeforeSelectionChange?: (info: SelectionInfo) => boolean | void;
184
- onBeforePaste?: (data: string[][]) => boolean | string[][] | void;
185
- onAfterPaste?: (data: string[][], info: { range: SelectionRange }) => void;
186
- onBeforeCopy?: (data: string[][], info: { range: SelectionRange }) => boolean | string[][] | void;
187
- onBeforeCut?: (data: string[][], info: { range: SelectionRange }) => boolean | string[][] | void;
188
- onAfterCopy?: (data: string[][], info: { range: SelectionRange; cut: boolean }) => void;
189
- onBeforeStructureChange?: (info: StructureInfo) => boolean | void;
190
- onStructureChange?: (info: StructureInfo) => void;
191
- onBeforeAutofill?: (src: SelectionRange, target: SelectionRange) => boolean | void;
192
- onAfterAutofill?: (src: SelectionRange, target: SelectionRange) => void;
193
- onBeforeKeyDown?: (e: KeyboardEvent) => boolean | void;
194
- onHeaderClick?: (c: number, e: MouseEvent) => boolean | void;
195
- onInvalid?: (rejections: Rejection[], source: ChangeSource) => void;
196
- onReadOnly?: (blocked: ReadOnlyBlock[], source: ChangeSource) => void;
197
- onChange?: (grid: TssGrid) => void;
198
- onPasteOverflow?: (info: { anchor: CellCoord; height: number; width: number; rows: number; cols: number; overRows: number; overCols: number }) => void;
199
-
200
- [k: string]: any;
201
- }
202
-
203
- export interface CsvOptions { formatted?: boolean; delimiter?: string; [k: string]: any; }
204
-
205
- /** Undo/Redo 履歴。複数グリッドで共有すると Undo タイムラインが繋がる。 */
206
- export declare class HistoryManager {
207
- constructor(max?: number);
208
- onChange: ((h: HistoryManager) => void) | null;
209
- push(cmd: { apply: () => void; revert: () => void }): void;
210
- undo(): void;
211
- redo(): void;
212
- clear(): void;
213
- canUndo(): boolean;
214
- canRedo(): boolean;
215
- }
216
-
217
- /**
218
- * 軽量・ノービルド・日本語IME堅牢な編集グリッド。
219
- * @example
220
- * const grid = new TssGrid(document.getElementById('app'), {
221
- * columns: [{ data: 'name', title: '品名' }, { data: 'qty', title: '数量', type: 'number' }],
222
- * data: [{ name: 'りんご', qty: 12 }],
223
- * });
224
- */
225
- export declare class TssGrid {
226
- constructor(container: HTMLElement, options?: TssGridOptions);
227
-
228
- /** 行数 / 列数(読み取り)。 */
229
- readonly ROWS: number;
230
- readonly COLS: number;
231
- /** 列定義(実行時参照)。 */
232
- columns: ColumnDef[];
233
- /** 履歴マネージャ。 */
234
- history: HistoryManager;
235
- /** Enter/Tab 確定後の移動方向(代入で即反映)。 */
236
- enterMoves: MoveDir;
237
- tabMoves: MoveDir;
238
-
239
- // ---- データ -------------------------------------------------------------
240
- /** 全データを2次元配列で取得(コピー)。 */
241
- getData(): any[][];
242
- /** 全行をオブジェクト配列で取得(columns[c].data キー基準)。 */
243
- getRows(): Record<string, any>[];
244
- /** r 行目をオブジェクトで取得。 */
245
- getRow(r: number): Record<string, any>;
246
- /** 列を縦に取得(index か data キー)。 */
247
- getColumn(cOrKey: number | string): any[] | undefined;
248
- /** 全列を配列の配列で取得。 */
249
- getColumns(): any[][];
250
- /** 1セルの値を取得(c は index か data キー)。 */
251
- getValue(r: number, cOrKey: number | string): any;
252
- /** データを差し替え(履歴・フィルタ・整列状態はリセット)。 */
253
- setData(rows: any[][] | Record<string, any>[]): void;
254
- /** 1セルに書き込み(履歴あり・検証/onBeforeChange 経由)。force=true で readOnly 貫通。 */
255
- setValue(r: number, cOrKey: number | string, val: any, force?: boolean): void;
256
- /** 履歴に積まず・検証も通さず直接書き込み(計算列など派生値用。readOnly 貫通)。 */
257
- setValueRaw(r: number, cOrKey: number | string, val: any): void;
258
-
259
- // ---- 並べ替え / フィルタ -------------------------------------------------
260
- /** 列で並べ替え(c は index か data キー)。 */
261
- sortBy(cOrKey: number | string, dir?: 'asc' | 'desc'): void;
262
- /** 比較関数で並べ替え。 */
263
- sortRows(cmp: (a: any[], b: any[]) => number): void;
264
- /** 並べ替え解除(入力順に戻す)。 */
265
- clearSort(): void;
266
- isSorted(): boolean;
267
- /** 非破壊フィルタ。pred(row, masterIndex, src)=>boolean、または { col: 値|fn }。 */
268
- filter(pred: ((row: any[], masterIndex: number, src: any) => boolean) | Record<string, any>): void;
269
- /** フィルタ解除(フィルタ中に編集/追加した行も含め全部戻る)。 */
270
- clearFilter(): void;
271
- isFiltered(): boolean;
272
- /** フィルタ中でも全行(マスタ)を取得。 */
273
- getAllRows(): Record<string, any>[];
274
-
275
- // ---- 選択 / カーソル ----------------------------------------------------
276
- setActive(r: number, c: number): void;
277
- setExtent(r: number, c: number): void;
278
- selectRect(r0: number, c0: number, r1: number, c1: number): void;
279
- selectRow(r: number): void;
280
- selectCol(c: number): void;
281
- selectAll(): void;
282
-
283
- // ---- 行 / 列 構造 -------------------------------------------------------
284
- insertRow(ri: number, where?: 'above' | 'below'): void;
285
- deleteRows(r0: number, r1?: number): void;
286
- insertCol(ci: number, where?: 'left' | 'right'): void;
287
- deleteCols(c0: number, c1?: number): void;
288
- /** 1行を移動(Undo 対応)。 */
289
- moveRow(from: number, to: number): void;
290
- /** 複数行をまとめて移動(Undo 対応)。 */
291
- moveRows(r0: number, r1: number, to: number): void;
292
-
293
- // ---- 列の表示 / 幅 / 固定 / 行高 ---------------------------------------
294
- hideColumn(c: number): void;
295
- showColumn(c: number): void;
296
- toggleColumn(c: number): void;
297
- isColumnHidden(c: number): boolean;
298
- getHiddenColumns(): number[];
299
- setColWidth(c: number, px: number): void;
300
- autoSizeColumn(c: number): void;
301
- autoSizeAllColumns(): void;
302
- freezeCols(n: number): void;
303
- freezeRows(n: number): void;
304
- setRowHeight(r: number, px: number): void;
305
-
306
- // ---- セル状態 / 検証 ----------------------------------------------------
307
- setAlignment(align: string, range?: SelectionRange): void;
308
- getAlignment(r: number, c: number): string;
309
- setCellReadOnly(flag: boolean, range?: SelectionRange): void;
310
- /** 今の全セルを検証し、NG を一覧で返す(保存前チェック等)。 */
311
- getInvalidCells(): Rejection[];
312
-
313
- // ---- 出力 / 再描画 / 破棄 ----------------------------------------------
314
- toCSV(opts?: CsvOptions): string;
315
- downloadCSV(filename: string, opts?: CsvOptions): void;
316
- /** 列定義変更後などの再描画(データ・選択は保持)。 */
317
- redraw(): void;
318
- /** 画像/フォント等の遅延レイアウト後に幾何キャッシュを再構築する保険。 */
319
- refreshGeometry(): void;
320
- /** グリッドを破棄(リスナ除去・DOM 撤去・idempotent)。フレームワークの teardown で呼ぶ。 */
321
- destroy(): void;
322
-
323
- // ---- 拡張 ---------------------------------------------------------------
324
- addShortcut(s: { name: string; keys: string; handler: (grid: TssGrid, e: KeyboardEvent) => void }): void;
325
- removeShortcut(name: string): void;
326
- usePlugin(plugin: ((grid: TssGrid, opts?: any) => any) | string, opts?: any): any;
327
- getPlugin(name: string): any;
328
-
329
- // ---- 低レベル(公開はするが通常は上位APIを推奨) -----------------------
330
- /** 選択範囲(または range)をクリア。※通常は値消去なら setValue('') を推奨。一括の低レベル手段。 */
331
- clearRange(): void;
332
- /** 選択範囲をクリップボードへ。cut=true で切り取り。 */
333
- copy(cut?: boolean): void;
334
- /** テーブルDOMを再構築(低レベル)。※通常は redraw() を推奨。主にプラグイン拡張者向け。 */
335
- buildTable(): void;
336
- /** セルの DOM 要素を返す(低レベル・内部DOM構造に依存)。結合セルはアンカーに解決。 */
337
- cellEl(r: number, c: number): HTMLTableCellElement | null;
338
-
339
- [k: string]: any;
340
- }
341
-
342
- // グローバル(<script> 読み込み時の window.TssGrid / window.HistoryManager)にも型を付ける。
343
- declare global {
344
- interface Window {
345
- TssGrid: typeof TssGrid;
346
- HistoryManager: typeof HistoryManager;
347
- }
348
- }
1
+ // =============================================================================
2
+ // TssGrid 型定義(公開APIの契約)
3
+ // - これが「外から呼べるもの」の正本。エディタ補完にはここに宣言したものだけ出る
4
+ // =内部メソッド(setCell / pushCmd / place など)は候補に出ず、自然に守られる。
5
+ // - 低レベルだが公開しているメソッドは JSDoc に「通常は○○を推奨」と明記(逃げ道は塞がない)。
6
+ // - v1 ドラフト。実装と差異を見つけたら本ファイルを正として揃える/直す。
7
+ // - 使い方:
8
+ // <script src="tssgrid.js"> 読み込み時 … グローバル TssGrid / HistoryManager に型が付く
9
+ // import { TssGrid } from 'tssgrid' … ESM entry 整備後(§npm化)に有効
10
+ // =============================================================================
11
+
12
+ export type MoveDir = 'down' | 'up' | 'right' | 'left' | 'none';
13
+ export type CellType = 'text' | 'number' | 'date' | 'time' | 'dropdown' | 'checkbox';
14
+ export type ChangeSource = 'edit' | 'paste' | 'fill' | 'delete' | 'undo' | 'redo';
15
+
16
+ /** 1つの値変更(onBeforeChange / onAfterChange の配列要素)。newValue を書き換えると整形確定。 */
17
+ export interface ChangeItem {
18
+ r: number;
19
+ c: number;
20
+ oldValue: any;
21
+ newValue: any;
22
+ source: ChangeSource;
23
+ }
24
+
25
+ /** 選択範囲。r0/c0=開始、r1/c1=終了(昇順とは限らない)。 */
26
+ export interface SelectionRange { r0: number; c0: number; r1: number; c1: number; }
27
+ export interface CellCoord { r: number; c: number; }
28
+ export interface SelectionInfo { range: SelectionRange; active: CellCoord; extent: CellCoord; }
29
+
30
+ /** validator が弾いたセル(onInvalid / getInvalidCells)。 */
31
+ export interface Rejection { r: number; c: number; value: any; code?: string; level?: string; message?: string; }
32
+ /** 読み取り専用セルへの変更を弾いた時(onReadOnly)。 */
33
+ export interface ReadOnlyBlock { r: number; c: number; value: any; }
34
+
35
+ /** 行/列の挿入・削除の情報(onStructureChange / onBeforeStructureChange)。 */
36
+ export interface StructureInfo { type: 'insertRow' | 'deleteRows' | 'insertCol' | 'deleteCols'; undo?: boolean; [k: string]: any; }
37
+
38
+ /** validator の戻り値: true=OK / 文字列=エラー文 / オブジェクト=メッセージカタログ解決用。 */
39
+ export type ValidatorResult = true | string | { code: string; params?: Record<string, any>; level?: string };
40
+
41
+ /** 列定義(options.columns[c])。`data` は data オブジェクトのキー(または列 index)。 */
42
+ export interface ColumnDef {
43
+ /** data オブジェクトのキー。配列データなら省略可(位置で対応)。 */
44
+ data?: string | number;
45
+ /** ヘッダ見出し(headers より優先)。 */
46
+ title?: string;
47
+ /** セルタイプ。既定 'text'。 */
48
+ type?: CellType;
49
+ /** dropdown の選択肢。 */
50
+ options?: Array<string | { value: string; label?: string }>;
51
+ /** 列ごとの初期幅(px)。列定義に同居=並べ替え/コピペで幅が追従。 */
52
+ width?: number;
53
+ /** false でこの列だけリサイズ禁止。 */
54
+ resizable?: boolean;
55
+ /** 列既定の水平/垂直整列。 */
56
+ align?: 'left' | 'center' | 'right';
57
+ valign?: 'top' | 'middle' | 'bottom';
58
+ /** 列単位の読み取り専用。関数でセル単位判定も可。 */
59
+ readOnly?: boolean | ((value: any, cell: CellCoord) => boolean);
60
+ /** 入力検証。編集/貼付/フィルの全経路に効く。 */
61
+ validator?: (value: any, cell: CellCoord) => ValidatorResult;
62
+ /** カスタム編集UI(薄いオブジェクト契約 or それを返す関数)。 */
63
+ editor?: object | (() => object);
64
+ /** 入力の正規化(保存値へ変換)。 */
65
+ parse?: (input: string, cell: CellCoord) => any;
66
+ /** 表示の整形(保存値→表示)。文字列 or 宣言的 CellFormat。 */
67
+ format?: string | object | ((value: any, cell: CellCoord) => string);
68
+ /** 数値型: 千区切り表示。 */
69
+ thousands?: boolean;
70
+ /** 数値型: 接頭辞(例 '¥')。 */
71
+ prefix?: string;
72
+ /** 値/行を見てセルに付与する CSS クラス(条件付き書式)。 */
73
+ cellClass?: (r: number, c: number, value: any, row: any) => string;
74
+ /** セル単位のインラインスタイル(連続色・データバー等)。 */
75
+ cellStyle?: (r: number, c: number, value: any, row: any) => Partial<CSSStyleDeclaration> | Record<string, string>;
76
+ /** true で表示だけ生HTML(値はテキスト保存のまま)。 */
77
+ html?: boolean;
78
+ /** 列単位の折り返し。 */
79
+ wordWrap?: boolean;
80
+ /** 複数行(改行)入力を有効化。編集は隠し textarea(IME 直打ち対応)、表示は改行保持(pre-wrap)。行高は自動で伸びないので rowHeights 等で確保する。 */
81
+ multiline?: boolean;
82
+ /** 空セルの薄いヒント文字。 */
83
+ placeholder?: string;
84
+ [k: string]: any;
85
+ }
86
+
87
+ /** new TssGrid(container, options) のオプション。 */
88
+ export interface TssGridOptions {
89
+ headers?: string[];
90
+ /** 初期データ。2次元配列 or オブジェクト配列。 */
91
+ data?: any[][] | Record<string, any>[];
92
+ /** 渡すと複数グリッドで Undo を共有。 */
93
+ history?: HistoryManager;
94
+ name?: string;
95
+ showDump?: boolean;
96
+ /** Enter 確定後の移動方向(既定 'down')。Shift で逆。実行時に書換可。 */
97
+ enterMoves?: MoveDir;
98
+ /** Tab 確定後の移動方向(既定 'right')。Shift で逆。実行時に書換可。 */
99
+ tabMoves?: MoveDir;
100
+ initialCell?: [number, number] | { r: number; c: number | string };
101
+ /** 入力フロー制御。Enter/Tab の移動先を上書き(null で既定方向)。入力セルだけ巡回できる。 */
102
+ nextCell?: (a: { r: number; c: number; key: string; shift: boolean }) => { r: number; c: number } | null;
103
+ columns?: ColumnDef[];
104
+ /** 検証NG時。'revert'=元に戻す / 'keep'=赤く警告して残す。 */
105
+ invalidMode?: 'revert' | 'keep';
106
+ invalidTitle?: boolean;
107
+ /** エラーの共通メッセージカタログ。 */
108
+ messages?: Record<string, any> | ((info: { code: string; params?: any; level?: string }) => string);
109
+ pasteOverflow?: 'clip' | 'error';
110
+ colWidths?: number[] | Record<string, number>;
111
+ rowHeights?: number[] | Record<string, number>;
112
+ defaultColWidth?: number;
113
+ defaultRowHeight?: number;
114
+ minColWidth?: number;
115
+ minRowHeight?: number;
116
+ resizeMode?: 'preview' | 'live';
117
+ /** 左から固定する列数。freezeCols(n) でも変更可。 */
118
+ frozenCols?: number;
119
+ /** 上から固定する行数。freezeRows(n) でも変更可。frozenCols 併用で四隅固定。 */
120
+ frozenRows?: number;
121
+ /** ヘッダ結合(複数段見出し)。最下段がリーフ=実列。 */
122
+ nestedHeaders?: Array<Array<string | { label: string; colspan?: number }>>;
123
+ width?: number | string;
124
+ height?: number | string;
125
+ resizeCols?: boolean;
126
+ resizeRows?: boolean;
127
+ /** false で選択カーソルを非表示(表示専用グリッド向け・内部選択は保持)。 */
128
+ cursor?: boolean;
129
+ stretchH?: 'none' | 'last' | 'all';
130
+ rowHeaders?: boolean;
131
+ /** 行番号列の幅(px)。既定 40。大量行で桁数が増える時に広げる。 */
132
+ rowHeaderWidth?: number;
133
+ /** 行ヘッダの表示内容。未指定=行番号(r+1) / false=数字なし(空) / (r)=>文字列=カスタム表示。 */
134
+ rowHeaderLabel?: false | ((r: number) => string | number);
135
+ /** 行のドラッグ並べ替え。true=行ヘッダーセルの ⠿ アイコンを掴んで移動 / 'header'=行ヘッダーセル全体が移動ハンドル(クリック=選択/ドラッグ=移動)。 */
136
+ rowReorder?: boolean | 'header';
137
+ /** 行ヘッダーの ⠿ マークの位置。'before'=番号の前(既定)/ 'after'=番号の後 / false=マークを出さない。 */
138
+ rowReorderMark?: 'before' | 'after' | false;
139
+ /** 仮想スクロール(固定行高ウィンドウイング)。大量行を可視窓だけ描画。true か { buffer:窓上下バッファ行数(既定6) }。
140
+ * 制約(v1): 行高一定/固定行列・折り返し・セル結合は非対応(指定時は自動無効化)。 */
141
+ virtual?: boolean | { buffer?: number };
142
+ colHeaders?: boolean;
143
+ hiddenColumns?: number[];
144
+ wordWrap?: boolean;
145
+ /** multiline 列の Enter 挙動。'commit'(既定・Excel風): Enter=確定 / Alt+Enter=改行。'newline'(メモ帳風): Enter=改行 / Ctrl+Enter=確定。 */
146
+ multilineEnter?: 'commit' | 'newline';
147
+ /** multiline セル右上の「複数行」ヒント表示(既定 true)。色は CSS 変数 --tg-ml-mark。false で非表示。 */
148
+ multilineMark?: boolean;
149
+ /** multiline 編集時に伸びる箱の最大行数(既定 10)。超えた分はボックス内スクロール。ビューポート/wrap を超える時はそちらが優先。 */
150
+ multilineEditMaxLines?: number;
151
+ placeholder?: string;
152
+ className?: string;
153
+ /** false でフィル完全OFF。詳細指定も可。 */
154
+ fillHandle?: boolean | { direction?: 'vertical' | 'horizontal' | 'both'; autoInsertRow?: boolean };
155
+ autoColumnSize?: boolean | number;
156
+ copyPaste?: boolean;
157
+ minSpareRows?: number;
158
+ autoWrapRow?: boolean;
159
+ autoWrapCol?: boolean;
160
+ minRows?: number;
161
+ maxRows?: number;
162
+ minCols?: number;
163
+ maxCols?: number;
164
+ /** グリッド全体を読み取り専用(ビューア用途)。 */
165
+ readOnly?: boolean;
166
+ /** 右クリックメニュー。true=既定 / false=無効 / 配列 or {items} =構成(組込キー文字列+カスタム MenuItem)。 */
167
+ contextMenu?: boolean | Array<string | MenuItem> | { items: Array<string | MenuItem> };
168
+ /** Ctrl+ヘッダで行/列を飛び飛び複数選択(既定 true)。false で Ctrl+クリックは単一選択に戻る。 */
169
+ disjointSelect?: boolean;
170
+ allowInsertRows?: boolean;
171
+ allowDeleteRows?: boolean;
172
+ allowInsertCols?: boolean;
173
+ allowDeleteCols?: boolean;
174
+ shortcuts?: any[];
175
+ /** プラグイン(関数 or 登録名)。init(grid) で初期化。 */
176
+ plugins?: any[];
177
+
178
+ // ---- イベント / コールバック -------------------------------------------
179
+ /** 確定の直前。検証・自動整形。false で全取消、change.newValue 書換で整形。 */
180
+ onBeforeChange?: (changes: ChangeItem[], source: ChangeSource) => boolean | void;
181
+ /** 確定の直後(undo/redo 含む)。保存・再計算に。 */
182
+ onAfterChange?: (changes: ChangeItem[], source: ChangeSource) => void;
183
+ onEditStart?: (info: { r: number; c: number; value: any }) => void;
184
+ onEditEnd?: (info: { r: number; c: number; oldValue: any; newValue: any; canceled: boolean }) => void;
185
+ onSelectionChange?: (info: SelectionInfo) => void;
186
+ onBeforeSelectionChange?: (info: SelectionInfo) => boolean | void;
187
+ onBeforePaste?: (data: string[][]) => boolean | string[][] | void;
188
+ onAfterPaste?: (data: string[][], info: { range: SelectionRange }) => void;
189
+ onBeforeCopy?: (data: string[][], info: { range: SelectionRange }) => boolean | string[][] | void;
190
+ onBeforeCut?: (data: string[][], info: { range: SelectionRange }) => boolean | string[][] | void;
191
+ onAfterCopy?: (data: string[][], info: { range: SelectionRange; cut: boolean }) => void;
192
+ onBeforeStructureChange?: (info: StructureInfo) => boolean | void;
193
+ onStructureChange?: (info: StructureInfo) => void;
194
+ onBeforeAutofill?: (src: SelectionRange, target: SelectionRange) => boolean | void;
195
+ onAfterAutofill?: (src: SelectionRange, target: SelectionRange) => void;
196
+ onBeforeKeyDown?: (e: KeyboardEvent) => boolean | void;
197
+ onHeaderClick?: (c: number, e: MouseEvent) => boolean | void;
198
+ /** 各列ヘッダ th の生成後に呼ぶ(再描画毎に自動で再実行)。ソートアイコン等の要素差し込み用。 */
199
+ onHeaderRender?: (th: HTMLTableCellElement, c: number) => void;
200
+ onInvalid?: (rejections: Rejection[], source: ChangeSource) => void;
201
+ onReadOnly?: (blocked: ReadOnlyBlock[], source: ChangeSource) => void;
202
+ onChange?: (grid: TssGrid) => void;
203
+ onPasteOverflow?: (info: { anchor: CellCoord; height: number; width: number; rows: number; cols: number; overRows: number; overCols: number }) => void;
204
+
205
+ [k: string]: any;
206
+ }
207
+
208
+ export interface CsvOptions {
209
+ headers?: boolean; formatted?: boolean; skipEmpty?: boolean; eol?: string;
210
+ /** CSV数式インジェクション無害化(既定 true)。=@+- 始まりの非数値セルを ' で保護。生値が要る用途は false。 */
211
+ sanitizeFormula?: boolean;
212
+ delimiter?: string; [k: string]: any;
213
+ }
214
+
215
+ /** 右クリックの対象種別。カスタムメニュー項目の name/disabled/hidden の第2引数、callback の {ctx} で受け取る。 */
216
+ export interface MenuContext { on: 'col' | 'row' | 'cell' | 'corner'; r: number; c: number; }
217
+
218
+ /** 右クリックメニューのカスタム項目。name/disabled/hidden は関数なら (range, ctx) で呼ばれる。 */
219
+ export interface MenuItem {
220
+ name?: string | ((range: SelectionRange, ctx: MenuContext) => string);
221
+ callback?: (arg: { range: SelectionRange; key?: string; ctx: MenuContext }) => void;
222
+ disabled?: boolean | ((range: SelectionRange, ctx: MenuContext) => boolean);
223
+ hidden?: boolean | ((range: SelectionRange, ctx: MenuContext) => boolean);
224
+ danger?: boolean; separator?: boolean; key?: string; submenu?: Array<string | MenuItem>;
225
+ }
226
+
227
+ /** Undo/Redo 履歴。複数グリッドで共有すると Undo タイムラインが繋がる。 */
228
+ export declare class HistoryManager {
229
+ constructor(max?: number);
230
+ onChange: ((h: HistoryManager) => void) | null;
231
+ push(cmd: { apply: () => void; revert: () => void }): void;
232
+ undo(): void;
233
+ redo(): void;
234
+ clear(): void;
235
+ canUndo(): boolean;
236
+ canRedo(): boolean;
237
+ }
238
+
239
+ /**
240
+ * 軽量・ノービルド・日本語IME堅牢な編集グリッド。
241
+ * @example
242
+ * const grid = new TssGrid(document.getElementById('app'), {
243
+ * columns: [{ data: 'name', title: '品名' }, { data: 'qty', title: '数量', type: 'number' }],
244
+ * data: [{ name: 'りんご', qty: 12 }],
245
+ * });
246
+ */
247
+ export declare class TssGrid {
248
+ constructor(container: HTMLElement, options?: TssGridOptions);
249
+
250
+ /** 行数 / 列数(読み取り)。 */
251
+ readonly ROWS: number;
252
+ readonly COLS: number;
253
+ /** 列定義(実行時参照)。 */
254
+ columns: ColumnDef[];
255
+ /** 履歴マネージャ。 */
256
+ history: HistoryManager;
257
+ /** Enter/Tab 確定後の移動方向(代入で即反映)。 */
258
+ enterMoves: MoveDir;
259
+ tabMoves: MoveDir;
260
+
261
+ // ---- データ -------------------------------------------------------------
262
+ /** 全データを2次元配列で取得(コピー)。 */
263
+ getData(): any[][];
264
+ /** 全行をオブジェクト配列で取得(columns[c].data キー基準)。 */
265
+ getRows(): Record<string, any>[];
266
+ /** r 行目をオブジェクトで取得。 */
267
+ getRow(r: number): Record<string, any>;
268
+ /** 列を縦に取得(index か data キー)。 */
269
+ getColumn(cOrKey: number | string): any[] | undefined;
270
+ /** 全列を配列の配列で取得。 */
271
+ getColumns(): any[][];
272
+ /** 1セルの値を取得(c は index か data キー)。 */
273
+ getValue(r: number, cOrKey: number | string): any;
274
+ /** データを差し替え(履歴・フィルタ・整列状態はリセット)。 */
275
+ setData(rows: any[][] | Record<string, any>[]): void;
276
+ /** 1セルに書き込み(履歴あり・検証/onBeforeChange 経由)。force=true で readOnly 貫通。 */
277
+ setValue(r: number, cOrKey: number | string, val: any, force?: boolean): void;
278
+ /** 履歴に積まず・検証も通さず直接書き込み(計算列など派生値用。readOnly 貫通)。 */
279
+ setValueRaw(r: number, cOrKey: number | string, val: any): void;
280
+
281
+ // ---- 並べ替え / フィルタ -------------------------------------------------
282
+ /** 列で並べ替え(c は index か data キー)。 */
283
+ sortBy(cOrKey: number | string, dir?: 'asc' | 'desc'): void;
284
+ /** 多段(複数列)で並べ替え。specs は優先順(先頭=第1キー)。各段は sortBy と同じ比較規則。 */
285
+ sortByCols(specs: Array<{ col: number | string; dir?: 'asc' | 'desc' }>): void;
286
+ /** 比較関数で並べ替え。 */
287
+ sortRows(cmp: (a: any[], b: any[]) => number): void;
288
+ /** 並べ替え解除(入力順に戻す)。 */
289
+ clearSort(): void;
290
+ isSorted(): boolean;
291
+ /** 非破壊フィルタ。pred(row, masterIndex, src)=>boolean、または { col: 値|fn }。 */
292
+ filter(pred: ((row: any[], masterIndex: number, src: any) => boolean) | Record<string, any>): void;
293
+ /** フィルタ解除(フィルタ中に編集/追加した行も含め全部戻る)。 */
294
+ clearFilter(): void;
295
+ isFiltered(): boolean;
296
+ /** フィルタ中でも全行(マスタ)を取得。 */
297
+ getAllRows(): Record<string, any>[];
298
+
299
+ // ---- 選択 / カーソル ----------------------------------------------------
300
+ setActive(r: number, c: number): void;
301
+ setExtent(r: number, c: number): void;
302
+ selectRect(r0: number, c0: number, r1: number, c1: number): void;
303
+ selectRow(r: number): void;
304
+ selectCol(c: number): void;
305
+ selectAll(): void;
306
+ /** 選択中の列インデックス(Ctrl+ヘッダクリックの飛び飛び選択に対応・昇順)。列選択モードでなければ `[]`。 */
307
+ getSelectedColumns(): number[];
308
+ /** 選択中の行インデックス(Ctrl+行ヘッダクリックの飛び飛び選択に対応・昇順)。行選択モードでなければ `[]`。 */
309
+ getSelectedRows(): number[];
310
+ /** 飛び飛びの複数列をまとめて削除(高index側から。右クリック「N 列を削除」の実体)。 */
311
+ deleteColsSet(cols: number[]): void;
312
+ /** 飛び飛びの複数行をまとめて削除(高index側から。右クリック「N 行を削除」の実体)。 */
313
+ deleteRowsSet(rows: number[]): void;
314
+
315
+ // ---- 行 / 列 構造 -------------------------------------------------------
316
+ insertRow(ri: number, where?: 'above' | 'below'): void;
317
+ deleteRows(r0: number, r1?: number): void;
318
+ insertCol(ci: number, where?: 'left' | 'right'): void;
319
+ deleteCols(c0: number, c1?: number): void;
320
+ /** 1行を移動(Undo 対応)。 */
321
+ moveRow(from: number, to: number): void;
322
+ /** 複数行をまとめて移動(Undo 対応)。 */
323
+ moveRows(r0: number, r1: number, to: number): void;
324
+
325
+ // ---- 列の表示 / 幅 / 固定 / 行高 ---------------------------------------
326
+ hideColumn(c: number): void;
327
+ showColumn(c: number): void;
328
+ toggleColumn(c: number): void;
329
+ isColumnHidden(c: number): boolean;
330
+ getHiddenColumns(): number[];
331
+ setColWidth(c: number, px: number): void;
332
+ autoSizeColumn(c: number): void;
333
+ autoSizeAllColumns(): void;
334
+ freezeCols(n: number): void;
335
+ freezeRows(n: number): void;
336
+ setRowHeight(r: number, px: number): void;
337
+
338
+ // ---- セル状態 / 検証 ----------------------------------------------------
339
+ setAlignment(align: string, range?: SelectionRange): void;
340
+ getAlignment(r: number, c: number): string;
341
+ setCellReadOnly(flag: boolean, range?: SelectionRange): void;
342
+ /** 今の全セルを検証し、NG を一覧で返す(保存前チェック等)。 */
343
+ getInvalidCells(): Rejection[];
344
+
345
+ // ---- 出力 / 再描画 / 破棄 ----------------------------------------------
346
+ toCSV(opts?: CsvOptions): string;
347
+ downloadCSV(filename: string, opts?: CsvOptions): void;
348
+ /** 列定義変更後などの再描画(データ・選択は保持)。 */
349
+ redraw(): void;
350
+ /** 画像/フォント等の遅延レイアウト後に幾何キャッシュを再構築する保険。 */
351
+ refreshGeometry(): void;
352
+ /** グリッドを破棄(リスナ除去・DOM 撤去・idempotent)。フレームワークの teardown で呼ぶ。 */
353
+ destroy(): void;
354
+
355
+ // ---- 拡張 ---------------------------------------------------------------
356
+ addShortcut(s: { name: string; keys: string; handler: (grid: TssGrid, e: KeyboardEvent) => void }): void;
357
+ removeShortcut(name: string): void;
358
+ usePlugin(plugin: ((grid: TssGrid, opts?: any) => any) | string, opts?: any): any;
359
+ getPlugin(name: string): any;
360
+
361
+ // ---- 低レベル(公開はするが通常は上位APIを推奨) -----------------------
362
+ /** 選択範囲(または range)をクリア。※通常は値消去なら setValue('') を推奨。一括の低レベル手段。 */
363
+ clearRange(): void;
364
+ /** 選択範囲をクリップボードへ。cut=true で切り取り。 */
365
+ copy(cut?: boolean): void;
366
+ /** テーブルDOMを再構築(低レベル)。※通常は redraw() を推奨。主にプラグイン拡張者向け。 */
367
+ buildTable(): void;
368
+ /** セルの DOM 要素を返す(低レベル・内部DOM構造に依存)。結合セルはアンカーに解決。 */
369
+ cellEl(r: number, c: number): HTMLTableCellElement | null;
370
+
371
+ [k: string]: any;
372
+ }
373
+
374
+ // グローバル(<script> 読み込み時の window.TssGrid / window.HistoryManager)にも型を付ける。
375
+ declare global {
376
+ interface Window {
377
+ TssGrid: typeof TssGrid;
378
+ HistoryManager: typeof HistoryManager;
379
+ }
380
+ }