@aiquants/virtualscroll 3.1.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +159 -1
- package/README.md +97 -3
- package/dist/ScrollBar.d.cts +9 -1
- package/dist/ScrollBar.d.ts +9 -1
- package/dist/ScrollBar.d.ts.map +1 -1
- package/dist/ScrollPane.d.cts +13 -0
- package/dist/ScrollPane.d.ts +13 -0
- package/dist/ScrollPane.d.ts.map +1 -1
- package/dist/TapScrollCircle.d.cts +7 -1
- package/dist/TapScrollCircle.d.ts +7 -1
- package/dist/TapScrollCircle.d.ts.map +1 -1
- package/dist/VirtualGrid.d.cts +472 -0
- package/dist/VirtualGrid.d.ts +473 -0
- package/dist/VirtualGrid.d.ts.map +1 -0
- package/dist/VirtualScroll.d.cts +47 -0
- package/dist/VirtualScroll.d.ts +47 -0
- package/dist/VirtualScroll.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2280 -1674
- package/dist/styles/virtualscroll.css +1 -1
- package/dist/styles/virtualscroll.standalone.css +1 -1
- package/dist/useFenwickMapTree.d.cts +7 -4
- package/dist/useFenwickMapTree.d.ts +7 -4
- package/dist/useFenwickMapTree.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ScrollBar.tsx +15 -3
- package/src/ScrollPane.tsx +46 -1
- package/src/TapScrollCircle.tsx +14 -5
- package/src/VirtualGrid.tsx +1822 -0
- package/src/VirtualScroll.tsx +30 -6
- package/src/index.ts +14 -0
- package/src/styles/virtualscroll.css +178 -0
- package/src/useFenwickMapTree.ts +34 -12
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ScrollPaneProps } from './ScrollPane.cjs';
|
|
3
|
+
import { useFenwickMapTree } from './useFenwickMapTree.cjs';
|
|
4
|
+
import { VirtualScrollBehaviorOptions, VirtualScrollScrollBarOptions } from './VirtualScroll.cjs';
|
|
5
|
+
/**
|
|
6
|
+
* Hard per-track size cap (px) for both axes. Values above this are rejected with a RangeError
|
|
7
|
+
* (fail-fast, no silent clamp): the §6 bounding contract `z × (ANCHOR_REBASE_DISTANCE +
|
|
8
|
+
* windowSpan) <= 2^24` relies on every track being bounded, and a single oversized track would
|
|
9
|
+
* let cell coordinates / the residual transform pierce the measured LayoutUnit wall (2^25).
|
|
10
|
+
*
|
|
11
|
+
* 両軸共通のトラックサイズ上限 (px)。超過は RangeError で fail-fast (暗黙 clamp なし):
|
|
12
|
+
* §6 の有界化契約はトラック有界性に立脚し、1 本の過大トラックでセル座標 / 残差 transform が
|
|
13
|
+
* 実測の LayoutUnit 壁 (2^25) を踏み抜くため。
|
|
14
|
+
*/
|
|
15
|
+
export declare const MAX_TRACK_SIZE = 262144;
|
|
16
|
+
/**
|
|
17
|
+
* Safety cap for cell nodes materialized in one render pass (rendered rows × rendered cols).
|
|
18
|
+
* Unlike the row-side MAX_RENDERED_ITEMS (a pathological-input guard), the 2D product can be
|
|
19
|
+
* reached by LEGITIMATE configurations (min zoom on large displays), so truncation is never
|
|
20
|
+
* silent — onRenderTruncated fires. Initial value assumes WQHD; §9-3 of the design plan owns
|
|
21
|
+
* the final calibration (4K floor ≈ 55,955).
|
|
22
|
+
*
|
|
23
|
+
* 1 レンダーで具現化するセルノード数 (描画行 × 描画列) の安全上限。行側 MAX_RENDERED_ITEMS
|
|
24
|
+
* (病的入力ガード) と違い、2D 積は正当な構成 (大型ディスプレイの最小ズーム) で到達し得るため
|
|
25
|
+
* 打切りは無言にしない — onRenderTruncated が発火する。初期値は WQHD 前提で、最終確定は
|
|
26
|
+
* 設計計画 §9-3 の所有 (4K の床 ≈ 55,955)。
|
|
27
|
+
*/
|
|
28
|
+
export declare const MAX_RENDERED_CELLS = 32768;
|
|
29
|
+
/**
|
|
30
|
+
* Hard cap for `frozenLeadingCols` (design §8). The frozen band is NOT windowed — every frozen
|
|
31
|
+
* column materializes in every rendered row and is EXEMPT from the MAX_RENDERED_CELLS
|
|
32
|
+
* truncation (the scroll-band budget is reduced by the frozen count instead) — so the cap is
|
|
33
|
+
* what bounds the band: worst case 128 x MAX_RENDERED_ITEMS rows, and W_F <= 128 x
|
|
34
|
+
* MAX_TRACK_SIZE = 2^25 (the measured layout wall; practical W_F <= viewport << 2^24). Real
|
|
35
|
+
* frozen panes are single-digit; violations fail fast with a RangeError.
|
|
36
|
+
*
|
|
37
|
+
* `frozenLeadingCols` の上限 (設計 §8)。凍結帯は窓化されず全描画行で具現化し、かつ
|
|
38
|
+
* MAX_RENDERED_CELLS の打切り対象外 (代わりにスクロール帯予算を凍結数ぶん控除) のため、帯を
|
|
39
|
+
* 有界にするのはこの上限そのもの: 最悪 128 × MAX_RENDERED_ITEMS 行、W_F ≤ 128 × MAX_TRACK_SIZE
|
|
40
|
+
* = 2^25 (実測壁ちょうど — 実運用は W_F ≤ viewport ≪ 2^24)。違反は fail-fast の RangeError。
|
|
41
|
+
*/
|
|
42
|
+
export declare const MAX_FROZEN_LEADING_COLS = 128;
|
|
43
|
+
/**
|
|
44
|
+
* Hard cap for `frozenLeadingRows` (frozen-rows design plan §4-1). The frozen-row band is
|
|
45
|
+
* grid-owned and OUT of the embedded VirtualScroll (index-shift architecture — plan §2):
|
|
46
|
+
* every band row materializes every rendered column and is exempt from MAX_RENDERED_CELLS
|
|
47
|
+
* (the budget denominator counts band rows instead), so the cap bounds the band itself.
|
|
48
|
+
* `frozenLeadingRows` の上限 (行凍結設計 §4-1)。凍結行帯はグリッド所有で埋め込み
|
|
49
|
+
* VirtualScroll の外 (インデックスシフト方式 — 設計 §2)。帯行は描画列を全て具現化し
|
|
50
|
+
* MAX_RENDERED_CELLS の打切り対象外 (予算分母に帯行数を算入) のため、帯を有界にするのは
|
|
51
|
+
* この上限そのもの。違反は fail-fast の RangeError。
|
|
52
|
+
*/
|
|
53
|
+
export declare const MAX_FROZEN_LEADING_ROWS = 128;
|
|
54
|
+
/**
|
|
55
|
+
* Hard cap for `frozenTrailingCols` (v3.5.0 trailing-freeze plan §3). The trailing band is NOT
|
|
56
|
+
* windowed — every trailing column materializes in every rendered row and is EXEMPT from the
|
|
57
|
+
* MAX_RENDERED_CELLS truncation (the scroll-band budget is reduced by the trailing count
|
|
58
|
+
* instead) — so the cap is what bounds the band: worst case 128 x MAX_RENDERED_ITEMS rows, and
|
|
59
|
+
* W_T <= 128 x MAX_TRACK_SIZE = 2^25 (the measured layout wall; practical W_T <= viewport <<
|
|
60
|
+
* 2^24). Violations fail fast with a RangeError.
|
|
61
|
+
*
|
|
62
|
+
* `frozenTrailingCols` の上限 (3.5.0 末尾凍結プラン §3)。末尾帯は窓化されず全描画行で具現化し、
|
|
63
|
+
* かつ MAX_RENDERED_CELLS の打切り対象外 (代わりにスクロール帯予算を末尾数ぶん控除) のため、
|
|
64
|
+
* 帯を有界にするのはこの上限そのもの: 最悪 128 × MAX_RENDERED_ITEMS 行、W_T ≤ 128 ×
|
|
65
|
+
* MAX_TRACK_SIZE = 2^25 (実測壁ちょうど — 実運用は W_T ≤ viewport ≪ 2^24)。違反は fail-fast の
|
|
66
|
+
* RangeError。
|
|
67
|
+
*/
|
|
68
|
+
export declare const MAX_FROZEN_TRAILING_COLS = 128;
|
|
69
|
+
/**
|
|
70
|
+
* Hard cap for `frozenTrailingRows` (v3.5.0 trailing-freeze plan §3). The trailing-row band is
|
|
71
|
+
* grid-owned and OUT of the embedded VirtualScroll (the SECOND out-of-pane band, below the
|
|
72
|
+
* pane): every band row materializes every rendered column and is exempt from
|
|
73
|
+
* MAX_RENDERED_CELLS (the budget denominator counts band rows instead), so the cap bounds the
|
|
74
|
+
* band itself. Violations fail fast with a RangeError.
|
|
75
|
+
*
|
|
76
|
+
* `frozenTrailingRows` の上限 (3.5.0 末尾凍結プラン §3)。末尾行帯はグリッド所有で埋め込み
|
|
77
|
+
* VirtualScroll の外 (ペインの**下**の第 2 帯外バンド)。帯行は描画列を全て具現化し
|
|
78
|
+
* MAX_RENDERED_CELLS の打切り対象外 (予算分母に帯行数を算入) のため、帯を有界にするのは
|
|
79
|
+
* この上限そのもの。違反は fail-fast の RangeError。
|
|
80
|
+
*/
|
|
81
|
+
export declare const MAX_FROZEN_TRAILING_ROWS = 128;
|
|
82
|
+
/**
|
|
83
|
+
* Resolves the per-row column cap from the cell budget and the effective rendered-row count.
|
|
84
|
+
* Pure and exported as the mutation-gate surface for the production MAX_RENDERED_CELLS fallback
|
|
85
|
+
* (the component itself is only ever gated through the __maxRenderedCells test seam).
|
|
86
|
+
*
|
|
87
|
+
* セル予算と実効描画行数から行あたり列上限を解決する。純関数 — 本番既定 MAX_RENDERED_CELLS への
|
|
88
|
+
* フォールバックを変異ゲート化するための export (コンポーネント側はテストシーム経由でしか
|
|
89
|
+
* ゲートできないため)。
|
|
90
|
+
*/
|
|
91
|
+
export declare const resolveMaxColsPerRow: (maxRenderedCells: number | undefined, renderedRowCount: number) => number;
|
|
92
|
+
/**
|
|
93
|
+
* Estimates the MATERIALIZED-row count of a commit that precedes the embedded VirtualScroll's
|
|
94
|
+
* range notification (the notification is a state update and lags one commit — mount and
|
|
95
|
+
* viewport resizes): walks row indices from `startRow` accumulating real heights until the
|
|
96
|
+
* viewport is filled, counting EVERY index — zero-height (hidden) rows materialize as DOM rows
|
|
97
|
+
* too, so counting only visible rows would under-divide the cell budget by the whole hidden run.
|
|
98
|
+
* The walk is capped by the shared MAX_RENDERED_ITEMS (the row axis truncates its own render at
|
|
99
|
+
* the same constant), then the rendering-window slack (2 x overscan + 2 boundary rows) is added.
|
|
100
|
+
*
|
|
101
|
+
* 内包 VirtualScroll の範囲通知 (state 更新のため 1 コミット遅れる — マウントとビューポート
|
|
102
|
+
* リサイズ) より前のコミットに対する**具現化行数**の見積り: `startRow` から実行高を積んで
|
|
103
|
+
* ビューポートを満たすまで**全 index** を数える — 高さ 0 (非表示) 行も DOM 行として具現化される
|
|
104
|
+
* ため、可視行だけを数えると隠しラン全量ぶんセル予算を過小分割する。ウォークは共有
|
|
105
|
+
* MAX_RENDERED_ITEMS (行軸自身の描画打切り定数) で上限化し、描画窓スラック (2 x overscan + 2)
|
|
106
|
+
* を足す。
|
|
107
|
+
*/
|
|
108
|
+
export declare const estimateRenderedRowCount: (viewportHeight: number, getRowHeight: (row: number) => number, rowCount: number, startRow: number, overscanRows: number) => number;
|
|
109
|
+
/**
|
|
110
|
+
* 2D range notification payload (rendering = overscan-inclusive, visible = strict; row-parity
|
|
111
|
+
* with VirtualScrollRange). The all-frozen scroll band reports the CANONICAL EMPTY window as
|
|
112
|
+
* start > end (renderingColStart = colCount, renderingColEnd = colCount - 1) — inclusive
|
|
113
|
+
* [start..end] loops naturally run zero iterations; formatters must handle start > end.
|
|
114
|
+
* 2D 範囲通知 (rendering = オーバースキャン込み、visible = 厳密 — 行側 VirtualScrollRange と
|
|
115
|
+
* 対称)。全列凍結のスクロール帯は**空窓の正準表現 start > end** (renderingColStart = colCount /
|
|
116
|
+
* renderingColEnd = colCount − 1) で通知する — 閉区間 [start..end] の列挙は自然に 0 周、
|
|
117
|
+
* 文言整形側は start > end を扱うこと。
|
|
118
|
+
*/
|
|
119
|
+
export type VirtualGridRange = {
|
|
120
|
+
renderingRowStart: number;
|
|
121
|
+
renderingRowEnd: number;
|
|
122
|
+
visibleRowStart: number;
|
|
123
|
+
visibleRowEnd: number;
|
|
124
|
+
renderingColStart: number;
|
|
125
|
+
renderingColEnd: number;
|
|
126
|
+
visibleColStart: number;
|
|
127
|
+
visibleColEnd: number;
|
|
128
|
+
/** Logical scroll position (px). / 論理スクロール位置 (px)。 */
|
|
129
|
+
scrollX: number;
|
|
130
|
+
scrollY: number;
|
|
131
|
+
totalWidth: number;
|
|
132
|
+
totalHeight: number;
|
|
133
|
+
};
|
|
134
|
+
/** Live-region options: the consumer owns wording/locale (no built-in strings — row-parity). / liveRegion オプション: 文言とロケールは消費側所有 (内蔵文字列なし — 行側と同一方針)。 */
|
|
135
|
+
export type VirtualGridLiveRegionOptions = {
|
|
136
|
+
/** Builds the announcement (same string = no re-announce, "" clears). / 読み上げ文言の組み立て (同一文字列 = 再読み上げなし、"" でクリア)。 */
|
|
137
|
+
buildMessage: (range: VirtualGridRange) => string;
|
|
138
|
+
/** Settle debounce before announcing (ms, default 400 — the row-side default). Must be finite and >= 0; anything else logs a warning and disables announcements (no silent substitution — row-parity contract). / 読み上げ前の静定待ち (ms、既定 400 — 行側と同一)。有限かつ 0 以上のみ — それ以外は警告して読み上げを無効化 (黙って既定へ読み替えない — 行側と同契約)。 */
|
|
139
|
+
debounceMs?: number;
|
|
140
|
+
};
|
|
141
|
+
/** Behavior options (embeds the vertical VirtualScrollBehaviorOptions + column-axis twins). / 挙動オプション (縦の VirtualScrollBehaviorOptions を包含 + 列軸双子)。 */
|
|
142
|
+
export type VirtualGridBehaviorOptions = VirtualScrollBehaviorOptions & {
|
|
143
|
+
/**
|
|
144
|
+
* Rebuilds the column width tree when getColWidth identity changes (the column twin of the
|
|
145
|
+
* row-side resetOnGetItemHeightChange — for mid-list column insert/delete where index↔width
|
|
146
|
+
* pairing shifts). Default false.
|
|
147
|
+
* getColWidth の identity 変化で列幅木を再構築する (行側 resetOnGetItemHeightChange の列
|
|
148
|
+
* 双子 — 中間挿入 / 削除で index↔幅 対応がずれる場合)。既定 false。
|
|
149
|
+
*/
|
|
150
|
+
resetOnGetColWidthChange?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Explicit Fenwick baseValue for the column width tree (design §3.4): skips the stride
|
|
153
|
+
* sampling of getColWidth at construction, so unmaterialized columns are estimated at exactly
|
|
154
|
+
* this width. Integer in [0, MAX_TRACK_SIZE] — RangeError otherwise (fail-fast, no clamp).
|
|
155
|
+
* 列幅木の Fenwick baseValue の明示指定 (設計 §3.4): 構築時の getColWidth ストライド
|
|
156
|
+
* サンプリングを省略し、未具現化列をこの幅で見積もる。[0, MAX_TRACK_SIZE] の整数 —
|
|
157
|
+
* 違反は RangeError (fail-fast、clamp なし)。
|
|
158
|
+
*/
|
|
159
|
+
defaultColWidth?: number;
|
|
160
|
+
};
|
|
161
|
+
/** Props for VirtualGrid. / VirtualGrid の props。 */
|
|
162
|
+
export type VirtualGridProps<T> = {
|
|
163
|
+
/** Row count (<= 2^53 - 1). / 行数 (≤ 2^53 − 1)。 */
|
|
164
|
+
rowCount: number;
|
|
165
|
+
/** Column count (<= 2^53 - 1 — full row-axis parity). / 列数 (≤ 2^53 − 1 — 行軸と完全対称)。 */
|
|
166
|
+
colCount: number;
|
|
167
|
+
/**
|
|
168
|
+
* Row height accessor — integer px, 0 = hidden, <= MAX_TRACK_SIZE (RangeError otherwise).
|
|
169
|
+
* Must stay index-stable while the ordering is unchanged (row-side getItemHeight contract).
|
|
170
|
+
* 行高アクセサ — 整数 px、0 = 非表示、≤ MAX_TRACK_SIZE (超過は RangeError)。並び順が
|
|
171
|
+
* 不変の間は index 安定であること (行側 getItemHeight と同文の契約)。
|
|
172
|
+
*/
|
|
173
|
+
getRowHeight: (row: number) => number;
|
|
174
|
+
/** Column width accessor — the width SSOT (same contract as getRowHeight; no eager bulk init is ever performed). / 列幅アクセサ — 幅の SSOT (getRowHeight と同契約。eager な一括初期化は行わない)。 */
|
|
175
|
+
getColWidth: (col: number) => number;
|
|
176
|
+
/** Cell value accessor (pull型 — the grid holds no data). / セル値アクセサ (pull 型 — グリッドはデータを持たない)。 */
|
|
177
|
+
getCell: (row: number, col: number) => T;
|
|
178
|
+
/** Stable cell key (default: the column index within the row). / 安定セルキー (既定: 行内の列 index)。 */
|
|
179
|
+
getCellKey?: (row: number, col: number) => string | number;
|
|
180
|
+
/** Cell renderer. / セルレンダラー。 */
|
|
181
|
+
children: (cell: T, row: number, col: number) => ReactNode;
|
|
182
|
+
/** Attributes merged onto the positioned cell element (roles / aria-* / data-* — the consumer hook surface). / 配置済みセル要素へマージする属性 (role / aria / data — 消費側フック面)。 */
|
|
183
|
+
getCellProps?: (row: number, col: number) => HTMLAttributes<HTMLDivElement>;
|
|
184
|
+
/** Attributes merged onto the row wrapper (role="row" / aria-rowindex). / 行ラッパーへマージする属性。 */
|
|
185
|
+
getRowProps?: (row: number) => HTMLAttributes<HTMLDivElement>;
|
|
186
|
+
/**
|
|
187
|
+
* ARIA / identity attributes for the scrollable content element (role="grid" etc.) — the
|
|
188
|
+
* EXACT row-side type (ScrollPaneProps["contentProps"]): deliberately NOT HTMLAttributes, so a
|
|
189
|
+
* consumer cannot smuggle className / style past the pane's structural class and inline
|
|
190
|
+
* geometry (the pane spreads contentProps after its own className — a wide type here would be
|
|
191
|
+
* a type-system bypass that clobbers overflow / position / flex in real browsers).
|
|
192
|
+
* スクロール面要素への ARIA / 識別属性 (role="grid" 等) — 行側と完全同型
|
|
193
|
+
* (ScrollPaneProps["contentProps"])。意図的に HTMLAttributes ではない: 広い型にすると
|
|
194
|
+
* className / style がペインの構造クラスとインライン形状を後勝ちで破壊できてしまう
|
|
195
|
+
* (型システムバイパス — 実ブラウザで overflow / position / flex が消える)。
|
|
196
|
+
*/
|
|
197
|
+
contentProps?: ScrollPaneProps["contentProps"];
|
|
198
|
+
/** Background layer rendered inside the content element behind the rows (row-side pass-through). / 行の背後・コンテンツ要素内に描画する背景レイヤー (行側の透過)。 */
|
|
199
|
+
background?: ReactNode;
|
|
200
|
+
/** Vertical content insets (px) around the rows (row-side pass-through — the horizontal axis has no inset concept in v1). / 行の上下コンテンツインセット (px、行側の透過 — 横軸のインセットは v1 非対応)。 */
|
|
201
|
+
contentInsets?: ScrollPaneProps["contentInsets"];
|
|
202
|
+
/** Fires when a row wrapper receives focus, in FULL row space (scroll rows via the +R-wrapped row-side onItemFocus — enableKeyboardNavigation applies; frozen band rows fire on direct DOM focus regardless). / 行ラッパーのフォーカス通知 (フル行空間)。スクロール行は +R ラップ済み行側 onItemFocus (enableKeyboardNavigation が前提)、凍結帯行は直接 DOM フォーカスで無条件発火。 */
|
|
203
|
+
onRowFocus?: (row: number) => void;
|
|
204
|
+
/**
|
|
205
|
+
* Keyboard gestures that horizontally scroll the grid-owned axis (default: none — the exact
|
|
206
|
+
* row-side prop; the emitted delta is consumed internally into hx). Requires
|
|
207
|
+
* behaviorOptions.enableKeyboardNavigation and focus on a row wrapper (row-side contract).
|
|
208
|
+
* グリッド所有の横軸をキーボードで動かす操作種別 (既定: 無効 — 行側と同一 prop。放出量は
|
|
209
|
+
* 内部で hx に消費)。behaviorOptions.enableKeyboardNavigation と行ラッパーへの
|
|
210
|
+
* フォーカスが前提 (行側と同契約)。
|
|
211
|
+
*/
|
|
212
|
+
horizontalKeyInputs?: readonly "arrow"[];
|
|
213
|
+
/** Pixels per horizontal arrow key press (default 40 — row-side pass-through incl. the reject-invalid contract). / 横矢印キー 1 回の移動量 (既定 40 — 不正値拒否契約ごと行側の透過)。 */
|
|
214
|
+
horizontalKeyStep?: number;
|
|
215
|
+
/** Fires on logical scroll (either axis). / 論理スクロール通知 (どちらの軸でも)。 */
|
|
216
|
+
onScroll?: (pos: {
|
|
217
|
+
x: number;
|
|
218
|
+
y: number;
|
|
219
|
+
}) => void;
|
|
220
|
+
/** Fires when the 2D rendering/visible ranges change. / 2D 範囲変化の通知。 */
|
|
221
|
+
onRangeChange?: (range: VirtualGridRange) => void;
|
|
222
|
+
/** Fires when the MAX_RENDERED_CELLS cap truncates columns (never silent). / MAX_RENDERED_CELLS 打切りの通知 (無言切り捨て禁止)。 */
|
|
223
|
+
onRenderTruncated?: (info: {
|
|
224
|
+
renderedCells: number;
|
|
225
|
+
droppedCols: number;
|
|
226
|
+
}) => void;
|
|
227
|
+
/** Vertical callback throttle passthrough (horizontal fires synchronously). / 縦コールバックのスロットル透過 (横は同期発火)。 */
|
|
228
|
+
callbackThrottleMs?: number;
|
|
229
|
+
/** Restores both axes from a {row, col, offsetY, offsetX} anchor (px-restore is refuted row-side — anchors survive estimation-space changes). / 両軸を {row, col, offsetY, offsetX} アンカーから復元 (生 px 復元は行側で反証済み)。 */
|
|
230
|
+
initialScrollAnchor?: {
|
|
231
|
+
row: number;
|
|
232
|
+
col: number;
|
|
233
|
+
offsetY: number;
|
|
234
|
+
offsetX: number;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Number of leading columns frozen at the left edge (design §8; default 0). The frozen band
|
|
238
|
+
* lives OUTSIDE the anchor machinery: tree coordinates [0, W_F) render as direct static
|
|
239
|
+
* lefts (safe — W_F <= viewport << 2^24), the scroll band's window search starts at the
|
|
240
|
+
* W_F offset, and its residual transform carries the -W_F origin-shift term. Non-negative
|
|
241
|
+
* integer <= MAX_FROZEN_LEADING_COLS — RangeError otherwise (fail-fast); values beyond the
|
|
242
|
+
* CURRENT colCount freeze every column (documented dynamic clamp, not a fallback — the
|
|
243
|
+
* scroll band then reports the EMPTY window start > end and renders no scroll cells).
|
|
244
|
+
* 左端に凍結する先頭列数 (設計 §8。既定 0)。凍結帯はアンカー機構の**外**: 木座標 [0, W_F)
|
|
245
|
+
* を静的 left で直接描画 (W_F は上限 128 × 2^18 = 2^25 で有界 — 実運用は viewport ≪ 2^24)、
|
|
246
|
+
* スクロール帯の窓探索は W_F
|
|
247
|
+
* オフセット始まり、残差 transform は −W_F の原点シフト項を持つ。0 以上の整数かつ
|
|
248
|
+
* MAX_FROZEN_LEADING_COLS 以下 — 違反は RangeError (fail-fast)。現在の colCount を超える
|
|
249
|
+
* 値は全列凍結 (文書化された動的クランプ — フォールバックではない)。
|
|
250
|
+
*/
|
|
251
|
+
frozenLeadingCols?: number;
|
|
252
|
+
/**
|
|
253
|
+
* Number of leading rows pinned at the top (frozen-rows design plan — default 0). The band
|
|
254
|
+
* is grid-owned and OUT of the embedded VirtualScroll: the scroll rows live in a SHIFTED
|
|
255
|
+
* index space (itemCount = rowCount − R, getItem = i + R), so vy is the scroll-band
|
|
256
|
+
* logical position and the vertical bar maps the band naturally. Non-negative integer <=
|
|
257
|
+
* MAX_FROZEN_LEADING_ROWS — RangeError otherwise (fail-fast); values beyond the CURRENT
|
|
258
|
+
* rowCount freeze every row (documented dynamic clamp — the scroll rows then report the
|
|
259
|
+
* canonical EMPTY window start > end and render nothing).
|
|
260
|
+
* 上端に凍結する先頭行数 (行凍結設計 — 既定 0)。帯はグリッド所有で埋め込み VirtualScroll
|
|
261
|
+
* の外: スクロール行は**シフト済みインデックス空間** (itemCount = rowCount − R、getItem =
|
|
262
|
+
* i + R) に住み、vy はスクロール帯の論理位置・縦バーは帯を自然に写像する。0 以上の整数
|
|
263
|
+
* かつ MAX_FROZEN_LEADING_ROWS 以下 — 違反は RangeError (fail-fast)。現在の rowCount を
|
|
264
|
+
* 超える値は全行凍結 (文書化された動的クランプ — スクロール行は正準空窓 start > end を
|
|
265
|
+
* 通知しゼロ描画)。
|
|
266
|
+
*/
|
|
267
|
+
frozenLeadingRows?: number;
|
|
268
|
+
/**
|
|
269
|
+
* Number of trailing columns frozen at the right edge (v3.5.0 trailing-freeze plan §3;
|
|
270
|
+
* default 0). Integer in [0, MAX_FROZEN_TRAILING_COLS] — RangeError otherwise (fail-fast).
|
|
271
|
+
* Dynamic clamp (documented contract): min(T, colCount − effectiveFrozenCols) — the LEADING
|
|
272
|
+
* band wins the count space. Trailing cells render in a right-anchored clip outside the
|
|
273
|
+
* anchor machinery (band-local lefts); `--aqvs-grid-trailing-width` is written iff T > 0.
|
|
274
|
+
* `scrollToCell` / `initialScrollAnchor` targeting a trailing column are horizontal no-ops
|
|
275
|
+
* (always visible). T = 0 is structurally identical to the pre-trailing DOM.
|
|
276
|
+
* 右端に凍結する末尾列数 (3.5.0 末尾凍結プラン §3。既定 0)。[0, MAX_FROZEN_TRAILING_COLS]
|
|
277
|
+
* の整数 — 違反は RangeError (fail-fast)。動的クランプ (文書化契約): min(T, colCount −
|
|
278
|
+
* effectiveFrozenCols) — カウント空間は**先頭が勝つ**。末尾セルはアンカー機構の外の
|
|
279
|
+
* 右アンカークリップに帯ローカル left で描画し、`--aqvs-grid-trailing-width` は T > 0 の
|
|
280
|
+
* ときのみ書かれる。`scrollToCell` / `initialScrollAnchor` の末尾列狙いは横 no-op
|
|
281
|
+
* (常時可視)。T = 0 は DOM 構造まで従来と恒等。
|
|
282
|
+
*/
|
|
283
|
+
frozenTrailingCols?: number;
|
|
284
|
+
/**
|
|
285
|
+
* Number of trailing rows pinned at the bottom (v3.5.0 trailing-freeze plan §3; default 0).
|
|
286
|
+
* Integer in [0, MAX_FROZEN_TRAILING_ROWS] — RangeError otherwise (fail-fast). Dynamic
|
|
287
|
+
* clamp (documented contract): min(T, rowCount − effectiveFrozenRows) — leading wins. The
|
|
288
|
+
* band is grid-owned BELOW the pane; the embedded scroll rows shrink at the TAIL only
|
|
289
|
+
* (itemCount = rowCount − R − T, getItem = i + R unchanged), so a runtime T change does NOT
|
|
290
|
+
* remount the embedded VirtualScroll (ADR-23). `scrollToCell` / `initialScrollAnchor`
|
|
291
|
+
* targeting a trailing row are vertical no-ops (always visible). T = 0 is structurally
|
|
292
|
+
* identical to the pre-trailing DOM.
|
|
293
|
+
* 下端に凍結する末尾行数 (3.5.0 末尾凍結プラン §3。既定 0)。[0, MAX_FROZEN_TRAILING_ROWS]
|
|
294
|
+
* の整数 — 違反は RangeError (fail-fast)。動的クランプ (文書化契約): min(T, rowCount −
|
|
295
|
+
* effectiveFrozenRows) — 先頭が勝つ。帯はペインの**下**のグリッド所有バンドで、埋め込み
|
|
296
|
+
* スクロール行は**末尾**だけが伸縮する (itemCount = rowCount − R − T、getItem = i + R
|
|
297
|
+
* 不変) — T の実行時変更は埋め込み VirtualScroll を再マウントしない (ADR-23)。
|
|
298
|
+
* `scrollToCell` / `initialScrollAnchor` の末尾行狙いは縦 no-op (常時可視)。T = 0 は
|
|
299
|
+
* DOM 構造まで従来と恒等。
|
|
300
|
+
*/
|
|
301
|
+
frozenTrailingRows?: number;
|
|
302
|
+
/** Row-axis overscan (default 3 — a declared, intentional deviation from the bare VirtualScroll default 15; see the bounding contract). / 行軸 overscan (既定 3 — 素の既定 15 からの宣言済み意図的乖離)。 */
|
|
303
|
+
overscanRows?: number;
|
|
304
|
+
/** Column-axis overscan (default 3). / 列軸 overscan (既定 3)。 */
|
|
305
|
+
overscanCols?: number;
|
|
306
|
+
/**
|
|
307
|
+
* Explicit root box size (px) — skips ResizeObserver self-measurement (the row-side
|
|
308
|
+
* viewportSize explicit-mode twin; deterministic for tests / SSR). The cell viewport is
|
|
309
|
+
* derived by subtracting the scrollbar thickness on both axes.
|
|
310
|
+
* ルート箱寸法の明示指定 (px) — RO 自己計測を省略する (行側 viewportSize 明示モードの双子。
|
|
311
|
+
* テスト / SSR の決定性)。セルビューポートは両軸ともバー厚を差し引いて導出する。
|
|
312
|
+
*/
|
|
313
|
+
viewportSize?: {
|
|
314
|
+
width: number;
|
|
315
|
+
height: number;
|
|
316
|
+
};
|
|
317
|
+
/** TEST-ONLY seam: overrides MAX_RENDERED_CELLS so the truncation path is gateable without materializing 32k DOM nodes in jsdom. / テスト専用シーム: 打切り経路を jsdom で 32k ノード無しにゲート化するための上限上書き。 */
|
|
318
|
+
__maxRenderedCells?: number;
|
|
319
|
+
behaviorOptions?: VirtualGridBehaviorOptions;
|
|
320
|
+
scrollBarOptions?: VirtualScrollScrollBarOptions;
|
|
321
|
+
liveRegion?: VirtualGridLiveRegionOptions;
|
|
322
|
+
className?: string;
|
|
323
|
+
testId?: string;
|
|
324
|
+
};
|
|
325
|
+
/** Imperative handle (logical coordinates everywhere; -1 sentinels pre-attach — row-parity incl. return values). / 命令ハンドル (全て論理座標・未接続 -1 番兵 — 返り値契約まで行側と対称)。 */
|
|
326
|
+
export type VirtualGridHandle = {
|
|
327
|
+
/**
|
|
328
|
+
* Jump API — do NOT use for continuous input (use scrollBy). Vertical delegates to the row
|
|
329
|
+
* scrollTo (which floors and pins a row anchor); horizontal clamps into [0, max] with no
|
|
330
|
+
* floor and no anchor pinning (the synthetic axis has no pane anchor — depth safety comes
|
|
331
|
+
* from quantized anchor rebasing instead). Returns the applied clamped position.
|
|
332
|
+
* ジャンプ API — 連続入力には使わない (scrollBy を使う)。縦は行 scrollTo へ委譲 (floor +
|
|
333
|
+
* 行アンカー張り)、横は [0, max] クランプのみで floor もアンカー張りも行わない (合成軸に
|
|
334
|
+
* ペインアンカーは無く、深度安全は量子化アンカー再基準化が担う)。クランプ後位置を返す。
|
|
335
|
+
*/
|
|
336
|
+
scrollTo(pos: {
|
|
337
|
+
x?: number;
|
|
338
|
+
y?: number;
|
|
339
|
+
}): {
|
|
340
|
+
x: number;
|
|
341
|
+
y: number;
|
|
342
|
+
};
|
|
343
|
+
/** Relative float-accumulating path (wheel semantics; returns the applied clamped position — drag loops consume it synchronously). / 相対 float 累積経路 (ホイール同義。クランプ後位置を同期 return — ドラッグループが消費)。 */
|
|
344
|
+
scrollBy(delta: {
|
|
345
|
+
x?: number;
|
|
346
|
+
y?: number;
|
|
347
|
+
}): {
|
|
348
|
+
x: number;
|
|
349
|
+
y: number;
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Cell-targeted jump. alignY uses the row vocabulary (top/bottom/center), alignX its
|
|
353
|
+
* horizontal twin (start/end/center). No "nearest". Targeting a LEADING frozen or TRAILING
|
|
354
|
+
* frozen column is a horizontal no-op that leaves any previously armed column anchor in
|
|
355
|
+
* place (the visual status quo is preserved; manual horizontal input clears anchors as
|
|
356
|
+
* usual); targeting a leading/trailing frozen row is a vertical no-op. Band membership is
|
|
357
|
+
* judged at CALL time — a T change AFTER arming follows the ADR-23 clamp semantics: a
|
|
358
|
+
* pending row anchor whose target row lands inside the trailing band after a T increase
|
|
359
|
+
* clamps to the last scroll row. Overlap registration (ADR-19-1): when the leading +
|
|
360
|
+
* trailing band extents exceed the viewport, occluded trailing cells cannot be scrolled
|
|
361
|
+
* into view — the no-op is exact there too.
|
|
362
|
+
* セル狙いジャンプ。"nearest" は無し。先頭 / 末尾凍結列狙いの横成分は no-op で、既存の
|
|
363
|
+
* 列アンカーはそのまま残る (視覚的現状維持 — 手動横入力が従来どおり解除する)。先頭 /
|
|
364
|
+
* 末尾凍結行狙いの縦成分も no-op。帯所属の判定は**呼出し時** — 張った後の T 変更は
|
|
365
|
+
* ADR-23 のクランプ意味論 (T 増加で末尾帯入りする行を狙った保留行アンカーは最終
|
|
366
|
+
* スクロール行へクランプ) に従う。重複登記 (ADR-19-1): 先頭 + 末尾の帯寸がビューポートを
|
|
367
|
+
* 超えるとき、隠れた末尾セルはどのスクロール位置でも可視化できない — no-op はそこでも正確。
|
|
368
|
+
*/
|
|
369
|
+
scrollToCell(row: number, col: number, options?: {
|
|
370
|
+
alignY?: "top" | "bottom" | "center";
|
|
371
|
+
alignX?: "start" | "end" | "center";
|
|
372
|
+
offsetX?: number;
|
|
373
|
+
offsetY?: number;
|
|
374
|
+
}): void;
|
|
375
|
+
/** Synchronous-fresh position read (internal refs — safe mid-event; {-1,-1} pre-attach). / 同期・最新の位置読み (内部 ref — イベント中も安全。未接続 {-1,-1})。 */
|
|
376
|
+
getScrollPosition(): {
|
|
377
|
+
x: number;
|
|
378
|
+
y: number;
|
|
379
|
+
};
|
|
380
|
+
/** {index, offset} anchor capture for exact restore; null when either count is 0, or the embedded scroll rows are absent (all-frozen OR a degenerate band whose H_F fills the viewport — both force itemCount 0, so there is no scroll row to anchor). / 厳密復元用アンカー捕獲。どちらかの count が 0、またはスクロール行が不在 (全行凍結 / H_F がビューポートを埋める縮退帯 — いずれも itemCount 0) なら null。 */
|
|
381
|
+
getScrollAnchor(): {
|
|
382
|
+
row: number;
|
|
383
|
+
col: number;
|
|
384
|
+
offsetX: number;
|
|
385
|
+
offsetY: number;
|
|
386
|
+
} | null;
|
|
387
|
+
getViewportSize(): {
|
|
388
|
+
width: number;
|
|
389
|
+
height: number;
|
|
390
|
+
};
|
|
391
|
+
getContentSize(): {
|
|
392
|
+
width: number;
|
|
393
|
+
height: number;
|
|
394
|
+
};
|
|
395
|
+
getRange(): VirtualGridRange | null;
|
|
396
|
+
/** Pair-call seam: getRowHeight stays the truth. 3-way split — leading band rows bump the frozen-row epoch, trailing band rows bump the trailing-row epoch (accessor re-read; the bands hold no tree), scroll rows delegate to the row updateItemSize at −R. / 対呼び出しシーム (getRowHeight が正)。3 分岐 — 先頭帯行は凍結行 epoch、末尾帯行は末尾行 epoch の繰上げ (アクセサ再読 — 帯に木は無い)、スクロール行は −R で行 updateItemSize へ委譲。 */
|
|
397
|
+
updateRowSize(row: number, px: number): void;
|
|
398
|
+
/**
|
|
399
|
+
* Column twin: validates (MAX_TRACK_SIZE fail-fast), updates the width tree, and bumps the
|
|
400
|
+
* width epoch so committed cells REPAINT even when the window key is unchanged (small grids,
|
|
401
|
+
* offsetting batch resizes). Multi-call batch loops coalesce into one recompute via React's
|
|
402
|
+
* automatic state batching (one commit per synchronous batch — the design's rAF-coalescing
|
|
403
|
+
* intent realized at commit granularity).
|
|
404
|
+
* 列双子: 検証 (fail-fast) → 幅木更新 → 幅エポックの繰上げで、窓キー不変でもコミット済み
|
|
405
|
+
* セルを再描画する (小さなグリッド・相殺バッチリサイズ)。連続呼び出しは React の自動
|
|
406
|
+
* バッチングで 1 コミットに合流 (設計の rAF 合流意図のコミット粒度での実現)。
|
|
407
|
+
*/
|
|
408
|
+
updateColSize(col: number, px: number): void;
|
|
409
|
+
/**
|
|
410
|
+
* Effective frozen-band sizes on both axes and both ends (v3.5.0 — a non-breaking field
|
|
411
|
+
* extension of the {cols, width} → {cols, width, rows, height} precedent). cols/rows/
|
|
412
|
+
* trailingCols/trailingRows = dynamic post-clamp counts; width/height/trailingWidth/
|
|
413
|
+
* trailingHeight = TREE px (the trailing sizes are tree SUFFIX sums); trailingVisibleWidth/
|
|
414
|
+
* trailingVisibleHeight = viewport-clipped `min(tree, max(0, viewport − leading))` — THE
|
|
415
|
+
* single source for W_T_vis / H_T_vis that every consumer judgment/write path cites (never
|
|
416
|
+
* re-derive the formula). Pre-attach the grid viewport reads {0, 0}, so the vis fields are
|
|
417
|
+
* 0 (an initial measured state, not a sentinel) while the tree fields stay tree px.
|
|
418
|
+
* 実効凍結帯寸法 — 両軸・両端 (v3.5.0。{cols, width} → {cols, width, rows, height} の
|
|
419
|
+
* 前例に続く非破壊のフィールド追加)。cols / rows / trailingCols / trailingRows は動的
|
|
420
|
+
* クランプ後の実効カウント、width / height / trailingWidth / trailingHeight は**木** px
|
|
421
|
+
* (末尾寸は木の接尾辞和)、trailingVisibleWidth / trailingVisibleHeight はビューポート
|
|
422
|
+
* クリップ `min(木, max(0, viewport − 先頭))` — W_T_vis / H_T_vis の**単一情報源**で、
|
|
423
|
+
* 消費側の判定 / 書込み経路は全てこのフィールドを名指しで読む (式の再導出禁止)。
|
|
424
|
+
* プレアタッチはビューポート {0, 0} のため vis フィールドは 0 (番兵ではなく初期実測状態)、
|
|
425
|
+
* 木フィールドは常に木 px。
|
|
426
|
+
*/
|
|
427
|
+
getFrozenSize(): {
|
|
428
|
+
cols: number;
|
|
429
|
+
width: number;
|
|
430
|
+
rows: number;
|
|
431
|
+
height: number;
|
|
432
|
+
trailingCols: number;
|
|
433
|
+
trailingRows: number;
|
|
434
|
+
trailingWidth: number;
|
|
435
|
+
trailingHeight: number;
|
|
436
|
+
trailingVisibleWidth: number;
|
|
437
|
+
trailingVisibleHeight: number;
|
|
438
|
+
};
|
|
439
|
+
/** 2-axis wheel bridge entry: vertical → embedded VirtualScroll, horizontal → hx. Returns whether the event was consumed (WheelBridgeTarget contract). / 2 軸ホイールブリッジ口。消費有無を返す (ブリッジ契約)。 */
|
|
440
|
+
applyWheel(event: WheelEvent): boolean;
|
|
441
|
+
/** Focuses the row wrapper at `row` (scroll rows via the −R-shifted row-side focusItemAtIndex — enableKeyboardNavigation applies; frozen band rows are focused directly and need no option). / 行ラッパーへフォーカス (スクロール行は −R シフトの行側 focusItemAtIndex — enableKeyboardNavigation が前提。凍結帯行は直接フォーカスでオプション不要)。 */
|
|
442
|
+
focusRowAtIndex(row: number, options?: {
|
|
443
|
+
ensureVisible?: boolean;
|
|
444
|
+
}): void;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Computes the column placement for one horizontal position: the rendering/visible ranges via
|
|
448
|
+
* the SHARED computeRenderingRanges (identical function to the row axis, huge branch included)
|
|
449
|
+
* plus the quantized column anchor. The anchor rebases only when the RENDERING-window start
|
|
450
|
+
* (overscan inclusive — the exact row-side basis) drifts beyond ANCHOR_REBASE_DISTANCE, so cell
|
|
451
|
+
* `left` (= absolute − anchor) and the wrapper residual stay small at any depth. Pure — exported
|
|
452
|
+
* as the primary mutation-gate surface.
|
|
453
|
+
*
|
|
454
|
+
* 1 つの横位置に対する列配置の算出: 共有 computeRenderingRanges (行軸と同一関数、huge 分岐
|
|
455
|
+
* 込み) による範囲 + 量子化列アンカー。アンカーは**描画窓 (オーバースキャン込み) 先頭**が
|
|
456
|
+
* ANCHOR_REBASE_DISTANCE を超えて離れたときだけ付替える (行側と同一基準) — セル left
|
|
457
|
+
* (= 絶対 − アンカー) と残差が任意深度で小さく保たれる。純関数 — 変異ゲートの主面として export。
|
|
458
|
+
*/
|
|
459
|
+
export declare const computeColumnPlacement: (hx: number, viewportWidth: number, overscanCols: number, colCount: number, getColWidth: (col: number) => number, colTree: ReturnType<typeof useFenwickMapTree>, totalWidth: number, prevAnchor: number) => {
|
|
460
|
+
renderingColStart: number;
|
|
461
|
+
renderingColEnd: number;
|
|
462
|
+
visibleColStart: number;
|
|
463
|
+
visibleColEnd: number;
|
|
464
|
+
colAnchor: number;
|
|
465
|
+
};
|
|
466
|
+
/**
|
|
467
|
+
* Generic 2D virtualization grid — see the fileoverview. Exposes VirtualGridHandle via ref.
|
|
468
|
+
* 汎用 2D 仮想化グリッド — fileoverview 参照。ref で VirtualGridHandle を公開する。
|
|
469
|
+
*/
|
|
470
|
+
export declare const VirtualGrid: <T>(props: VirtualGridProps<T> & {
|
|
471
|
+
ref?: React.Ref<VirtualGridHandle>;
|
|
472
|
+
}) => ReactNode;
|