@aiquants/spreadsheet 0.10.0 → 0.12.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/dist/index.d.cts CHANGED
@@ -1043,11 +1043,22 @@ export declare type ReadOnlyRejection = {
1043
1043
  readonly cellCount: number;
1044
1044
  };
1045
1045
 
1046
- /** Public custom cell renderer context (ADR-8). / 公開セルレンダラーの ctx (ADR-8)。 */
1046
+ /**
1047
+ * Public custom cell renderer context (ADR-8). `text` is the RAW canonical `getCellText`
1048
+ * string; `displayText` (v0.12) is the value-format display string — the exact string the
1049
+ * default rendering, the AT announcement, the HTML clipboard and autofit all share (equals
1050
+ * `text` when the format capability is absent). A custom cell that should look like the
1051
+ * default renders `displayText`.
1052
+ * 公開セルレンダラーの ctx (ADR-8)。`text` は素の正準 `getCellText` 文字列。`displayText`
1053
+ * (v0.12) は値書式の表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit が共有
1054
+ * する同一文字列 (書式能力なしは `text` と同値)。既定と同じ見た目にしたいカスタムセルは
1055
+ * `displayText` を描く。
1056
+ */
1047
1057
  export declare type RenderCellContext = {
1048
1058
  row: number;
1049
1059
  col: number;
1050
1060
  text: string;
1061
+ displayText: string;
1051
1062
  };
1052
1063
 
1053
1064
  /**
@@ -1271,10 +1282,12 @@ export declare type SpreadsheetDataAdapter = {
1271
1282
  * string only — editing keeps the raw getCellText (Excel semantics) and copy/TSV carry the raw
1272
1283
  * value too (a DELIBERATE deviation from Excel, which copies the display — raw preserves the
1273
1284
  * numeric round-trip). Autofit measures the FORMATTED display, and screen-reader
1274
- * announcements receive both the raw text and the display string. `renderCell` (a prop)
1275
- * takes precedence over the built-in VALUE format (raw text flows to the custom renderer),
1276
- * but the resolved ALIGNMENT and paint are cell properties that still apply under
1277
- * renderCell. Every format is fail-soft: a non-numeric value in a numeric format, an
1285
+ * announcements receive both the raw text and the display string. A `renderCell` (prop)
1286
+ * cell that returns custom output shows that output instead of the built-in VALUE format
1287
+ * (raw `text` and the formatted `displayText` both flow to the custom renderer); a cell whose
1288
+ * renderCell returns `undefined` falls back to the formatted default (v0.12 per-cell opt-out),
1289
+ * and the resolved ALIGNMENT and paint are cell properties that apply under renderCell
1290
+ * regardless. Every format is fail-soft: a non-numeric value in a numeric format, an
1278
1291
  * invalid date, an out-of-range Intl option or an unparseable colour renders / paints
1279
1292
  * nothing for that key. Return a shared/interned CellFormat per column (or per cell object)
1280
1293
  * to avoid per-cell allocation and to keep the paint intern stable; because return values
@@ -1288,9 +1301,10 @@ export declare type SpreadsheetDataAdapter = {
1288
1301
  * **塗り書式** (この base ⊕ 条件付き書式)。値書式は表示文字列にのみ適用し、編集は素の
1289
1302
  * getCellText (Excel 意味論)、コピー / TSV も素の値を運ぶ (Excel は表示を写すため**意図的な
1290
1303
  * 逸脱** — 素値は数値の往復を保つ)。autofit は**整形後の表示**を計測し、読み上げには素の
1291
- * text と表示文字列の両方を渡す。`renderCell` (prop) は組み込み「値書式」に優先する (素の
1292
- * text がカスタムレンダラーへ) が、解決済み「揃え」と塗りはセル固有属性として renderCell 下
1293
- * でも効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1304
+ * text と表示文字列の両方を渡す。`renderCell` (prop) がカスタム出力を返したセルは組み込み
1305
+ * 「値書式」の代わりにその出力を描く (素の text と整形後 displayText の両方がカスタム
1306
+ * レンダラーへ)。undefined を返したセルは整形済みの既定描画へ降りる (v0.12 のセル単位
1307
+ * オプトアウト)。解決済み「揃え」と塗りはセル固有属性として renderCell 下でも常に効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1294
1308
  * 不能な色はそのキーだけ何も描かない。列毎 (またはセル object 毎) に共有 CellFormat を返すと
1295
1309
  * セル毎の確保を避け塗りの intern も安定する。戻り値は (getCellText 同様) 再スライス時のみ
1296
1310
  * 再読込されるため、書式変更の反映は dataVersion 増分 (またはアダプタ差替) で行う。
@@ -1403,6 +1417,31 @@ export declare type SpreadsheetDataAdapter = {
1403
1417
  * (getCellText と同格、描画パスでも呼ばれるため)。未宣言 = 全セル編集可 = 従来挙動とバイト同一。
1404
1418
  */
1405
1419
  isCellReadOnly?: (row: number, col: number) => boolean;
1420
+ /**
1421
+ * OPTIONAL capability (v0.12): host-owned `data-*` attributes for one cell, merged verbatim
1422
+ * onto the PACKAGE-OWNED cell element (`[data-aqsp-cell]`) so host CSS can target cell
1423
+ * state, `:hover` and theme tokens without wrapper elements inside the cell. The package
1424
+ * never interprets the values. Validated fail-fast at render (RangeError): the return must
1425
+ * be a plain record or `null` (a JS host's `undefined` / array / Map is rejected by name,
1426
+ * never a bare TypeError), every key must be a lowercase `data-*` name
1427
+ * (`data-[a-z0-9-]+`), the package- and engine-emitted cell attributes (`data-aqsp*`,
1428
+ * `data-aqvs*`, `data-row`, `data-col`) are reserved, and every value must be a string
1429
+ * (React would otherwise stringify objects or drop `undefined` silently). Read once per
1430
+ * painted cell per slice (the `getCellText` cost budget — keep it O(1)); publish changes
1431
+ * via `dataVersion`. `null` = no extra attributes for this cell. Absence = the previous
1432
+ * version's cell DOM byte-identically.
1433
+ * 任意能力 (v0.12): セル 1 つへのホスト所有 `data-*` 属性 — パッケージ所有のセル要素
1434
+ * (`[data-aqsp-cell]`) へそのまま載せる継ぎ目。セル内に器 (ラッパー要素) を敷かずにホスト
1435
+ * CSS がセル状態・`:hover`・テーマトークンを掴むための口で、値の解釈はパッケージが
1436
+ * 持たない。render 時 fail-fast 検証 (RangeError): 戻りはプレーンな record か `null`
1437
+ * (JS ホストの `undefined` / 配列 / Map は名指しで拒否 — 生 TypeError にしない)、キーは
1438
+ * 小文字 `data-*` (`data-[a-z0-9-]+`) のみ、パッケージ / エンジン放出のセル属性
1439
+ * (`data-aqsp*` / `data-aqvs*` / `data-row` / `data-col`) は予約、値は string のみ (React の
1440
+ * 暗黙文字列化や `undefined` の無言脱落を許さない)。描画セル毎・スライス毎に 1 読み
1441
+ * (getCellText と同格の予算 — O(1) に保つ)。変更は dataVersion で公開。null = このセルに
1442
+ * 追加属性なし。未宣言 = 従来のセル DOM とバイト同一。
1443
+ */
1444
+ getCellAttributes?: (row: number, col: number) => Readonly<Record<string, string>> | null;
1406
1445
  /**
1407
1446
  * OPTIONAL capability (v0.8): the numeric minimum / maximum over a range, for colorScale
1408
1447
  * rules whose end points omit `value`; null = the range holds no numeric value. Memoised by
@@ -1678,10 +1717,95 @@ export declare type SpreadsheetProps = {
1678
1717
  * 宣言の不在信号 (エンジン既定) で、本パッケージでの値フォールバックなし。
1679
1718
  */
1680
1719
  tapScrollCircleOptions?: ScrollBarTapCircleOptions;
1720
+ /**
1721
+ * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1722
+ * rendered beyond each vertical viewport edge. This slack is the only thing absorbing the
1723
+ * engine's one-frame rendering-window lag during fast scrolling (the blank-band remedy).
1724
+ * Overscan counts ROWS — hidden 0-height rows consume slots too — so the px slack per edge
1725
+ * is overscan × row height only where rows are uniform and visible. Undefined ⇒ the engine
1726
+ * default (3). The engine does not validate overscan (a negative value silently shrinks the
1727
+ * rendering window), so THIS surface owns the fail-fast: a non-integer or negative value
1728
+ * throws a RangeError at render. Cost multiplies with the column axis, and the engine
1729
+ * TRUNCATES rather than bounds: a window beyond its per-axis row budget or its total cell
1730
+ * cap keeps the LEADING side and drops the trailing side — the row-budget case has no
1731
+ * callback (the engine only logs a warning), the cell-cap case (columns dropped) reports
1732
+ * through `onRenderTruncated`. Values of
1733
+ * hundreds of rows per side approach that budget on tall viewports; keep overscan to the
1734
+ * slack you need.
1735
+ * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1736
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策)。
1737
+ * overscan は**行数**で数える (非表示の 0px 行も枠を消費) ため、片端の余裕 px が overscan ×
1738
+ * 行高になるのは行が一様に可視のときだけ。undefined はエンジン既定 (3)。エンジンは overscan を
1739
+ * 検証しない (負値は描画窓を無言で縮める) ため fail-fast は本層所有 — 非整数・負値は render 時
1740
+ * RangeError。費用は列軸との積で増幅し、エンジンは有界化でなく**打切り**で応じる: 軸毎の行予算
1741
+ * や総セル上限を超えた窓は先頭側を残し末尾側を落とす — 行予算超過はコールバック無し (エンジンは
1742
+ * warn ログのみ)、セル上限超過 (列の脱落) は `onRenderTruncated` で通知。片側数百行の値は高い viewport で予算に迫るため、必要な
1743
+ * 余裕にとどめる。
1744
+ */
1745
+ overscanRows?: number;
1746
+ /**
1747
+ * Column-axis overscan pass-through (the VirtualGrid `overscanCols` knob; LIVE prop) — the
1748
+ * column twin of `overscanRows`, same validation contract (non-negative integer or
1749
+ * RangeError; undefined ⇒ engine default 3).
1750
+ * 列軸 overscan の素通し (VirtualGrid `overscanCols`。ライブ prop) — `overscanRows` の
1751
+ * 列双子。検証契約は同文 (非負整数、それ以外 RangeError。undefined ⇒ エンジン既定 3)。
1752
+ */
1753
+ overscanCols?: number;
1754
+ /**
1755
+ * Background layer rendered behind the scroll-band rows, inside the engine content element
1756
+ * (the VirtualGrid `background` pass-through; LIVE prop). VIEWPORT-PINNED: the engine
1757
+ * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1758
+ * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1759
+ * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1760
+ * not to row-aligned gridlines. The layer spans the full width of the scroll rows — the
1761
+ * frozen-COLUMN region included (frozen columns live inside the scroll rows) — but not the
1762
+ * frozen row bands. Identity-stable contract (same as `renderCell`): an inline element here
1763
+ * pierces the GridBody memo boundary on every host re-render (the engine's render bodies
1764
+ * re-run; cells stay memoized) — hoist the node or `useMemo` it.
1765
+ * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1766
+ * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1767
+ * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1768
+ * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1769
+ * 行整合の罫線には不向き。層はスクロール行の全幅 — 凍結**列**域を含む (凍結列はスクロール行の
1770
+ * 内側に居る) — に広がり、凍結行帯には広がらない。identity 安定契約 (`renderCell` と同じ):
1771
+ * インライン要素はホスト再レンダー毎に GridBody の memo 境界を貫通する (エンジンの render 本体が
1772
+ * 再実行、セルは memo 維持) — ノードは hoist するか `useMemo` で保つ。
1773
+ */
1774
+ background?: ReactNode;
1775
+ /**
1776
+ * Rendering-truncation signal pass-through (the VirtualGrid `onRenderTruncated` callback):
1777
+ * fires when the engine drops trailing columns to stay under its total cell cap
1778
+ * (`MAX_RENDERED_CELLS`) — the cells actually rendered and the columns dropped. The engine's
1779
+ * doctrine is that truncation is never silent; an oversized `overscanCols` × row span is the
1780
+ * typical cause. Undefined ⇒ no callback (engine default).
1781
+ * 描画打切り通知の素通し (VirtualGrid `onRenderTruncated`): エンジンが総セル上限
1782
+ * (`MAX_RENDERED_CELLS`) を守るため末尾列を落としたときに、実描画セル数と脱落列数で発火する。
1783
+ * 「打切りは無言にしない」がエンジン教義で、過大な `overscanCols` × 行スパンが典型原因。
1784
+ * undefined = 通知なし (エンジン既定)。
1785
+ */
1786
+ onRenderTruncated?: (info: {
1787
+ renderedCells: number;
1788
+ droppedCols: number;
1789
+ }) => void;
1681
1790
  /**
1682
1791
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1683
1792
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
1684
- * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。
1793
+ * Per-cell opt-out (v0.12): returning `undefined` from one cell lands that cell on the
1794
+ * package default rendering (value-format engine included) — "custom where needed, default
1795
+ * elsewhere" without wrapper elements. ONLY `undefined` opts out — `null`, `false` (the
1796
+ * `cond && <X/>` idiom) and every other ReactNode are custom output, i.e. an empty custom
1797
+ * cell. `ctx.text` is the RAW canonical string; `ctx.displayText` (v0.12) is the value-format
1798
+ * display — the exact string the default rendering, the AT announcement, the HTML clipboard
1799
+ * and autofit share, so a custom cell that renders it can never drift from what gets copied.
1800
+ * Autofit stays a whole-grid no-op while `renderCell` is set (custom DOM width is unknowable).
1801
+ * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。セル単位
1802
+ * オプトアウト (v0.12): `undefined` を返したセルはパッケージ既定描画 (値書式エンジン込み) へ
1803
+ * 降りる — 「要る列だけカスタム、残りは既定」を器なしで構成できる。オプトアウトは
1804
+ * `undefined` **だけ** — `null` / `false` (`cond && <X/>` 慣用) / 他の ReactNode はカスタム
1805
+ * 出力 (= 空のカスタムセル)。`ctx.text` は素の正準文字列、`ctx.displayText` (v0.12) は値書式の
1806
+ * 表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit と同一なので、これを描く
1807
+ * カスタムセルはコピー結果と食い違わない。autofit は `renderCell` 指定中はグリッド全体
1808
+ * no-op のまま (カスタム DOM の幅は測れない)。
1685
1809
  */
1686
1810
  renderCell?: (ctx: RenderCellContext) => ReactNode;
1687
1811
  /**
@@ -1689,11 +1813,16 @@ export declare type SpreadsheetProps = {
1689
1813
  * paste replace, Ctrl+A, ...). Never during a drag (state frozen — one fire at pointerup),
1690
1814
  * with ONE documented in-drag firing point: the header subtract reservation converts to a
1691
1815
  * real press on the first movement, firing the deferred press replace mid-drag (total fire
1692
- * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. Independent
1693
- * of the live region's 200ms debounce (firing point: the §6.9-1 setSelection wrapper).
1816
+ * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. ONE host-driven
1817
+ * fire point outside gestures (ADR-33): a same-adapter rowCount / colCount shrink that moved
1818
+ * the selection fires once from a layout effect of that commit — not a user gesture.
1819
+ * Independent of the live region's 200ms debounce (firing point: the §6.9-1 setSelection
1820
+ * wrapper).
1694
1821
  * 確定 SelectionState が変わるたびに発火。ドラッグ中と初期マウントでは発火しない。明文の
1695
1822
  * ドラッグ中発火点が 1 つ: ヘッダー減算予約の実 press 変換 (初動 move) は遅延 press 置換を
1696
- * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。
1823
+ * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。ジェスチャ外のホスト起点発火点が
1824
+ * 1 つ (ADR-33): 同一 adapter の rowCount / colCount 縮小で選択が動いたとき、その commit の
1825
+ * layout effect から 1 回発火する (ユーザー操作ではない)。
1697
1826
  */
1698
1827
  onSelectionChange?: (selection: SelectionState) => void;
1699
1828
  /** Consumer context menu (§6.4.3-4 / §6.6.1 Shift+F10); keyboard origin carries the active cell viewport rect. / consumer コンテキストメニュー。 */
@@ -1797,9 +1926,11 @@ export declare type SpreadsheetProps = {
1797
1926
  enableResizeUI?: boolean;
1798
1927
  /**
1799
1928
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1800
- * is the RAW canonical getCellText; `displayText` is what a sighted user sees (the
1929
+ * is the RAW canonical getCellText; `displayText` is the value-format display string (the
1801
1930
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1802
- * hear "87.0%" for a cell whose raw value is "0.87". `readOnly` (v0.10) is
1931
+ * hear "87.0%" for a cell whose raw value is "0.87". It is the same string a custom
1932
+ * `renderCell` cell receives as `ctx.displayText` (v0.12) — what a sighted user sees unless
1933
+ * the host deliberately renders something else. `readOnly` (v0.10) is
1803
1934
  * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1804
1935
  * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1805
1936
  * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
@@ -1985,6 +2116,15 @@ declare type SpreadsheetTestProps = {
1985
2116
  * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
1986
2117
  */
1987
2118
  __onVirtualKeyboardRaise?: () => void;
2119
+ /**
2120
+ * Test-only rendered-cell cap forwarded to the engine's `__maxRenderedCells` seam so the
2121
+ * `onRenderTruncated` pass-through can be pinned without materializing 32,768 cells. Never
2122
+ * passed in production (unset = the engine's MAX_RENDERED_CELLS — the `__onCellRender` conduct).
2123
+ * テスト専用の描画セル上限 (エンジンの `__maxRenderedCells` シームへ素通し) — `onRenderTruncated`
2124
+ * 素通しを 32,768 セルの実体化なしでピンするため。production では渡さない (未指定 = エンジンの
2125
+ * MAX_RENDERED_CELLS — `__onCellRender` と同じ品行)。
2126
+ */
2127
+ __maxRenderedCells?: number;
1988
2128
  };
1989
2129
 
1990
2130
  export { TapScrollCircleRenderProps }
package/dist/index.d.ts CHANGED
@@ -1043,11 +1043,22 @@ export declare type ReadOnlyRejection = {
1043
1043
  readonly cellCount: number;
1044
1044
  };
1045
1045
 
1046
- /** Public custom cell renderer context (ADR-8). / 公開セルレンダラーの ctx (ADR-8)。 */
1046
+ /**
1047
+ * Public custom cell renderer context (ADR-8). `text` is the RAW canonical `getCellText`
1048
+ * string; `displayText` (v0.12) is the value-format display string — the exact string the
1049
+ * default rendering, the AT announcement, the HTML clipboard and autofit all share (equals
1050
+ * `text` when the format capability is absent). A custom cell that should look like the
1051
+ * default renders `displayText`.
1052
+ * 公開セルレンダラーの ctx (ADR-8)。`text` は素の正準 `getCellText` 文字列。`displayText`
1053
+ * (v0.12) は値書式の表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit が共有
1054
+ * する同一文字列 (書式能力なしは `text` と同値)。既定と同じ見た目にしたいカスタムセルは
1055
+ * `displayText` を描く。
1056
+ */
1047
1057
  export declare type RenderCellContext = {
1048
1058
  row: number;
1049
1059
  col: number;
1050
1060
  text: string;
1061
+ displayText: string;
1051
1062
  };
1052
1063
 
1053
1064
  /**
@@ -1271,10 +1282,12 @@ export declare type SpreadsheetDataAdapter = {
1271
1282
  * string only — editing keeps the raw getCellText (Excel semantics) and copy/TSV carry the raw
1272
1283
  * value too (a DELIBERATE deviation from Excel, which copies the display — raw preserves the
1273
1284
  * numeric round-trip). Autofit measures the FORMATTED display, and screen-reader
1274
- * announcements receive both the raw text and the display string. `renderCell` (a prop)
1275
- * takes precedence over the built-in VALUE format (raw text flows to the custom renderer),
1276
- * but the resolved ALIGNMENT and paint are cell properties that still apply under
1277
- * renderCell. Every format is fail-soft: a non-numeric value in a numeric format, an
1285
+ * announcements receive both the raw text and the display string. A `renderCell` (prop)
1286
+ * cell that returns custom output shows that output instead of the built-in VALUE format
1287
+ * (raw `text` and the formatted `displayText` both flow to the custom renderer); a cell whose
1288
+ * renderCell returns `undefined` falls back to the formatted default (v0.12 per-cell opt-out),
1289
+ * and the resolved ALIGNMENT and paint are cell properties that apply under renderCell
1290
+ * regardless. Every format is fail-soft: a non-numeric value in a numeric format, an
1278
1291
  * invalid date, an out-of-range Intl option or an unparseable colour renders / paints
1279
1292
  * nothing for that key. Return a shared/interned CellFormat per column (or per cell object)
1280
1293
  * to avoid per-cell allocation and to keep the paint intern stable; because return values
@@ -1288,9 +1301,10 @@ export declare type SpreadsheetDataAdapter = {
1288
1301
  * **塗り書式** (この base ⊕ 条件付き書式)。値書式は表示文字列にのみ適用し、編集は素の
1289
1302
  * getCellText (Excel 意味論)、コピー / TSV も素の値を運ぶ (Excel は表示を写すため**意図的な
1290
1303
  * 逸脱** — 素値は数値の往復を保つ)。autofit は**整形後の表示**を計測し、読み上げには素の
1291
- * text と表示文字列の両方を渡す。`renderCell` (prop) は組み込み「値書式」に優先する (素の
1292
- * text がカスタムレンダラーへ) が、解決済み「揃え」と塗りはセル固有属性として renderCell 下
1293
- * でも効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1304
+ * text と表示文字列の両方を渡す。`renderCell` (prop) がカスタム出力を返したセルは組み込み
1305
+ * 「値書式」の代わりにその出力を描く (素の text と整形後 displayText の両方がカスタム
1306
+ * レンダラーへ)。undefined を返したセルは整形済みの既定描画へ降りる (v0.12 のセル単位
1307
+ * オプトアウト)。解決済み「揃え」と塗りはセル固有属性として renderCell 下でも常に効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1294
1308
  * 不能な色はそのキーだけ何も描かない。列毎 (またはセル object 毎) に共有 CellFormat を返すと
1295
1309
  * セル毎の確保を避け塗りの intern も安定する。戻り値は (getCellText 同様) 再スライス時のみ
1296
1310
  * 再読込されるため、書式変更の反映は dataVersion 増分 (またはアダプタ差替) で行う。
@@ -1403,6 +1417,31 @@ export declare type SpreadsheetDataAdapter = {
1403
1417
  * (getCellText と同格、描画パスでも呼ばれるため)。未宣言 = 全セル編集可 = 従来挙動とバイト同一。
1404
1418
  */
1405
1419
  isCellReadOnly?: (row: number, col: number) => boolean;
1420
+ /**
1421
+ * OPTIONAL capability (v0.12): host-owned `data-*` attributes for one cell, merged verbatim
1422
+ * onto the PACKAGE-OWNED cell element (`[data-aqsp-cell]`) so host CSS can target cell
1423
+ * state, `:hover` and theme tokens without wrapper elements inside the cell. The package
1424
+ * never interprets the values. Validated fail-fast at render (RangeError): the return must
1425
+ * be a plain record or `null` (a JS host's `undefined` / array / Map is rejected by name,
1426
+ * never a bare TypeError), every key must be a lowercase `data-*` name
1427
+ * (`data-[a-z0-9-]+`), the package- and engine-emitted cell attributes (`data-aqsp*`,
1428
+ * `data-aqvs*`, `data-row`, `data-col`) are reserved, and every value must be a string
1429
+ * (React would otherwise stringify objects or drop `undefined` silently). Read once per
1430
+ * painted cell per slice (the `getCellText` cost budget — keep it O(1)); publish changes
1431
+ * via `dataVersion`. `null` = no extra attributes for this cell. Absence = the previous
1432
+ * version's cell DOM byte-identically.
1433
+ * 任意能力 (v0.12): セル 1 つへのホスト所有 `data-*` 属性 — パッケージ所有のセル要素
1434
+ * (`[data-aqsp-cell]`) へそのまま載せる継ぎ目。セル内に器 (ラッパー要素) を敷かずにホスト
1435
+ * CSS がセル状態・`:hover`・テーマトークンを掴むための口で、値の解釈はパッケージが
1436
+ * 持たない。render 時 fail-fast 検証 (RangeError): 戻りはプレーンな record か `null`
1437
+ * (JS ホストの `undefined` / 配列 / Map は名指しで拒否 — 生 TypeError にしない)、キーは
1438
+ * 小文字 `data-*` (`data-[a-z0-9-]+`) のみ、パッケージ / エンジン放出のセル属性
1439
+ * (`data-aqsp*` / `data-aqvs*` / `data-row` / `data-col`) は予約、値は string のみ (React の
1440
+ * 暗黙文字列化や `undefined` の無言脱落を許さない)。描画セル毎・スライス毎に 1 読み
1441
+ * (getCellText と同格の予算 — O(1) に保つ)。変更は dataVersion で公開。null = このセルに
1442
+ * 追加属性なし。未宣言 = 従来のセル DOM とバイト同一。
1443
+ */
1444
+ getCellAttributes?: (row: number, col: number) => Readonly<Record<string, string>> | null;
1406
1445
  /**
1407
1446
  * OPTIONAL capability (v0.8): the numeric minimum / maximum over a range, for colorScale
1408
1447
  * rules whose end points omit `value`; null = the range holds no numeric value. Memoised by
@@ -1678,10 +1717,95 @@ export declare type SpreadsheetProps = {
1678
1717
  * 宣言の不在信号 (エンジン既定) で、本パッケージでの値フォールバックなし。
1679
1718
  */
1680
1719
  tapScrollCircleOptions?: ScrollBarTapCircleOptions;
1720
+ /**
1721
+ * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1722
+ * rendered beyond each vertical viewport edge. This slack is the only thing absorbing the
1723
+ * engine's one-frame rendering-window lag during fast scrolling (the blank-band remedy).
1724
+ * Overscan counts ROWS — hidden 0-height rows consume slots too — so the px slack per edge
1725
+ * is overscan × row height only where rows are uniform and visible. Undefined ⇒ the engine
1726
+ * default (3). The engine does not validate overscan (a negative value silently shrinks the
1727
+ * rendering window), so THIS surface owns the fail-fast: a non-integer or negative value
1728
+ * throws a RangeError at render. Cost multiplies with the column axis, and the engine
1729
+ * TRUNCATES rather than bounds: a window beyond its per-axis row budget or its total cell
1730
+ * cap keeps the LEADING side and drops the trailing side — the row-budget case has no
1731
+ * callback (the engine only logs a warning), the cell-cap case (columns dropped) reports
1732
+ * through `onRenderTruncated`. Values of
1733
+ * hundreds of rows per side approach that budget on tall viewports; keep overscan to the
1734
+ * slack you need.
1735
+ * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1736
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策)。
1737
+ * overscan は**行数**で数える (非表示の 0px 行も枠を消費) ため、片端の余裕 px が overscan ×
1738
+ * 行高になるのは行が一様に可視のときだけ。undefined はエンジン既定 (3)。エンジンは overscan を
1739
+ * 検証しない (負値は描画窓を無言で縮める) ため fail-fast は本層所有 — 非整数・負値は render 時
1740
+ * RangeError。費用は列軸との積で増幅し、エンジンは有界化でなく**打切り**で応じる: 軸毎の行予算
1741
+ * や総セル上限を超えた窓は先頭側を残し末尾側を落とす — 行予算超過はコールバック無し (エンジンは
1742
+ * warn ログのみ)、セル上限超過 (列の脱落) は `onRenderTruncated` で通知。片側数百行の値は高い viewport で予算に迫るため、必要な
1743
+ * 余裕にとどめる。
1744
+ */
1745
+ overscanRows?: number;
1746
+ /**
1747
+ * Column-axis overscan pass-through (the VirtualGrid `overscanCols` knob; LIVE prop) — the
1748
+ * column twin of `overscanRows`, same validation contract (non-negative integer or
1749
+ * RangeError; undefined ⇒ engine default 3).
1750
+ * 列軸 overscan の素通し (VirtualGrid `overscanCols`。ライブ prop) — `overscanRows` の
1751
+ * 列双子。検証契約は同文 (非負整数、それ以外 RangeError。undefined ⇒ エンジン既定 3)。
1752
+ */
1753
+ overscanCols?: number;
1754
+ /**
1755
+ * Background layer rendered behind the scroll-band rows, inside the engine content element
1756
+ * (the VirtualGrid `background` pass-through; LIVE prop). VIEWPORT-PINNED: the engine
1757
+ * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1758
+ * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1759
+ * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1760
+ * not to row-aligned gridlines. The layer spans the full width of the scroll rows — the
1761
+ * frozen-COLUMN region included (frozen columns live inside the scroll rows) — but not the
1762
+ * frozen row bands. Identity-stable contract (same as `renderCell`): an inline element here
1763
+ * pierces the GridBody memo boundary on every host re-render (the engine's render bodies
1764
+ * re-run; cells stay memoized) — hoist the node or `useMemo` it.
1765
+ * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1766
+ * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1767
+ * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1768
+ * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1769
+ * 行整合の罫線には不向き。層はスクロール行の全幅 — 凍結**列**域を含む (凍結列はスクロール行の
1770
+ * 内側に居る) — に広がり、凍結行帯には広がらない。identity 安定契約 (`renderCell` と同じ):
1771
+ * インライン要素はホスト再レンダー毎に GridBody の memo 境界を貫通する (エンジンの render 本体が
1772
+ * 再実行、セルは memo 維持) — ノードは hoist するか `useMemo` で保つ。
1773
+ */
1774
+ background?: ReactNode;
1775
+ /**
1776
+ * Rendering-truncation signal pass-through (the VirtualGrid `onRenderTruncated` callback):
1777
+ * fires when the engine drops trailing columns to stay under its total cell cap
1778
+ * (`MAX_RENDERED_CELLS`) — the cells actually rendered and the columns dropped. The engine's
1779
+ * doctrine is that truncation is never silent; an oversized `overscanCols` × row span is the
1780
+ * typical cause. Undefined ⇒ no callback (engine default).
1781
+ * 描画打切り通知の素通し (VirtualGrid `onRenderTruncated`): エンジンが総セル上限
1782
+ * (`MAX_RENDERED_CELLS`) を守るため末尾列を落としたときに、実描画セル数と脱落列数で発火する。
1783
+ * 「打切りは無言にしない」がエンジン教義で、過大な `overscanCols` × 行スパンが典型原因。
1784
+ * undefined = 通知なし (エンジン既定)。
1785
+ */
1786
+ onRenderTruncated?: (info: {
1787
+ renderedCells: number;
1788
+ droppedCols: number;
1789
+ }) => void;
1681
1790
  /**
1682
1791
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1683
1792
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
1684
- * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。
1793
+ * Per-cell opt-out (v0.12): returning `undefined` from one cell lands that cell on the
1794
+ * package default rendering (value-format engine included) — "custom where needed, default
1795
+ * elsewhere" without wrapper elements. ONLY `undefined` opts out — `null`, `false` (the
1796
+ * `cond && <X/>` idiom) and every other ReactNode are custom output, i.e. an empty custom
1797
+ * cell. `ctx.text` is the RAW canonical string; `ctx.displayText` (v0.12) is the value-format
1798
+ * display — the exact string the default rendering, the AT announcement, the HTML clipboard
1799
+ * and autofit share, so a custom cell that renders it can never drift from what gets copied.
1800
+ * Autofit stays a whole-grid no-op while `renderCell` is set (custom DOM width is unknowable).
1801
+ * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。セル単位
1802
+ * オプトアウト (v0.12): `undefined` を返したセルはパッケージ既定描画 (値書式エンジン込み) へ
1803
+ * 降りる — 「要る列だけカスタム、残りは既定」を器なしで構成できる。オプトアウトは
1804
+ * `undefined` **だけ** — `null` / `false` (`cond && <X/>` 慣用) / 他の ReactNode はカスタム
1805
+ * 出力 (= 空のカスタムセル)。`ctx.text` は素の正準文字列、`ctx.displayText` (v0.12) は値書式の
1806
+ * 表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit と同一なので、これを描く
1807
+ * カスタムセルはコピー結果と食い違わない。autofit は `renderCell` 指定中はグリッド全体
1808
+ * no-op のまま (カスタム DOM の幅は測れない)。
1685
1809
  */
1686
1810
  renderCell?: (ctx: RenderCellContext) => ReactNode;
1687
1811
  /**
@@ -1689,11 +1813,16 @@ export declare type SpreadsheetProps = {
1689
1813
  * paste replace, Ctrl+A, ...). Never during a drag (state frozen — one fire at pointerup),
1690
1814
  * with ONE documented in-drag firing point: the header subtract reservation converts to a
1691
1815
  * real press on the first movement, firing the deferred press replace mid-drag (total fire
1692
- * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. Independent
1693
- * of the live region's 200ms debounce (firing point: the §6.9-1 setSelection wrapper).
1816
+ * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. ONE host-driven
1817
+ * fire point outside gestures (ADR-33): a same-adapter rowCount / colCount shrink that moved
1818
+ * the selection fires once from a layout effect of that commit — not a user gesture.
1819
+ * Independent of the live region's 200ms debounce (firing point: the §6.9-1 setSelection
1820
+ * wrapper).
1694
1821
  * 確定 SelectionState が変わるたびに発火。ドラッグ中と初期マウントでは発火しない。明文の
1695
1822
  * ドラッグ中発火点が 1 つ: ヘッダー減算予約の実 press 変換 (初動 move) は遅延 press 置換を
1696
- * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。
1823
+ * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。ジェスチャ外のホスト起点発火点が
1824
+ * 1 つ (ADR-33): 同一 adapter の rowCount / colCount 縮小で選択が動いたとき、その commit の
1825
+ * layout effect から 1 回発火する (ユーザー操作ではない)。
1697
1826
  */
1698
1827
  onSelectionChange?: (selection: SelectionState) => void;
1699
1828
  /** Consumer context menu (§6.4.3-4 / §6.6.1 Shift+F10); keyboard origin carries the active cell viewport rect. / consumer コンテキストメニュー。 */
@@ -1797,9 +1926,11 @@ export declare type SpreadsheetProps = {
1797
1926
  enableResizeUI?: boolean;
1798
1927
  /**
1799
1928
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1800
- * is the RAW canonical getCellText; `displayText` is what a sighted user sees (the
1929
+ * is the RAW canonical getCellText; `displayText` is the value-format display string (the
1801
1930
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1802
- * hear "87.0%" for a cell whose raw value is "0.87". `readOnly` (v0.10) is
1931
+ * hear "87.0%" for a cell whose raw value is "0.87". It is the same string a custom
1932
+ * `renderCell` cell receives as `ctx.displayText` (v0.12) — what a sighted user sees unless
1933
+ * the host deliberately renders something else. `readOnly` (v0.10) is
1803
1934
  * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1804
1935
  * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1805
1936
  * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
@@ -1985,6 +2116,15 @@ declare type SpreadsheetTestProps = {
1985
2116
  * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
1986
2117
  */
1987
2118
  __onVirtualKeyboardRaise?: () => void;
2119
+ /**
2120
+ * Test-only rendered-cell cap forwarded to the engine's `__maxRenderedCells` seam so the
2121
+ * `onRenderTruncated` pass-through can be pinned without materializing 32,768 cells. Never
2122
+ * passed in production (unset = the engine's MAX_RENDERED_CELLS — the `__onCellRender` conduct).
2123
+ * テスト専用の描画セル上限 (エンジンの `__maxRenderedCells` シームへ素通し) — `onRenderTruncated`
2124
+ * 素通しを 32,768 セルの実体化なしでピンするため。production では渡さない (未指定 = エンジンの
2125
+ * MAX_RENDERED_CELLS — `__onCellRender` と同じ品行)。
2126
+ */
2127
+ __maxRenderedCells?: number;
1988
2128
  };
1989
2129
 
1990
2130
  export { TapScrollCircleRenderProps }