@aiquants/spreadsheet 0.11.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
@@ -1681,16 +1720,27 @@ export declare type SpreadsheetProps = {
1681
1720
  /**
1682
1721
  * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1683
1722
  * rendered beyond each vertical viewport edge. This slack is the only thing absorbing the
1684
- * engine's one-frame rendering-window lag during fast scrolling (the blank-band remedy —
1685
- * the slack in px is overscan × row height per edge). Undefined ⇒ the engine default (3).
1686
- * The engine clamps invalid values silently, so THIS surface owns the fail-fast: a
1687
- * non-integer or negative value throws a RangeError at render. Cost multiplies with the
1688
- * column axis (bounded by the engine cell cap).
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.
1689
1735
  * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1690
- * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策 —
1691
- * 余裕 px は片端あたり overscan × 行高)。undefined はエンジン既定 (3)。エンジンは不正値を
1692
- * 無言クランプするため fail-fast は本層所有 — 非整数・負値は render 時 RangeError。費用は
1693
- * 列軸との積で増幅 (エンジンのセル上限で有界)。
1736
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策)。
1737
+ * overscan は**行数**で数える (非表示の 0px 行も枠を消費) ため、片端の余裕 px が overscan ×
1738
+ * 行高になるのは行が一様に可視のときだけ。undefined はエンジン既定 (3)。エンジンは overscan を
1739
+ * 検証しない (負値は描画窓を無言で縮める) ため fail-fast は本層所有 — 非整数・負値は render 時
1740
+ * RangeError。費用は列軸との積で増幅し、エンジンは有界化でなく**打切り**で応じる: 軸毎の行予算
1741
+ * や総セル上限を超えた窓は先頭側を残し末尾側を落とす — 行予算超過はコールバック無し (エンジンは
1742
+ * warn ログのみ)、セル上限超過 (列の脱落) は `onRenderTruncated` で通知。片側数百行の値は高い viewport で予算に迫るため、必要な
1743
+ * 余裕にとどめる。
1694
1744
  */
1695
1745
  overscanRows?: number;
1696
1746
  /**
@@ -1707,18 +1757,55 @@ export declare type SpreadsheetProps = {
1707
1757
  * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1708
1758
  * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1709
1759
  * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1710
- * not to row-aligned gridlines.
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.
1711
1765
  * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1712
1766
  * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1713
1767
  * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1714
1768
  * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1715
- * 行整合の罫線には不向き。
1769
+ * 行整合の罫線には不向き。層はスクロール行の全幅 — 凍結**列**域を含む (凍結列はスクロール行の
1770
+ * 内側に居る) — に広がり、凍結行帯には広がらない。identity 安定契約 (`renderCell` と同じ):
1771
+ * インライン要素はホスト再レンダー毎に GridBody の memo 境界を貫通する (エンジンの render 本体が
1772
+ * 再実行、セルは memo 維持) — ノードは hoist するか `useMemo` で保つ。
1716
1773
  */
1717
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;
1718
1790
  /**
1719
1791
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1720
1792
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
1721
- * 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 の幅は測れない)。
1722
1809
  */
1723
1810
  renderCell?: (ctx: RenderCellContext) => ReactNode;
1724
1811
  /**
@@ -1726,11 +1813,16 @@ export declare type SpreadsheetProps = {
1726
1813
  * paste replace, Ctrl+A, ...). Never during a drag (state frozen — one fire at pointerup),
1727
1814
  * with ONE documented in-drag firing point: the header subtract reservation converts to a
1728
1815
  * real press on the first movement, firing the deferred press replace mid-drag (total fire
1729
- * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. Independent
1730
- * 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).
1731
1821
  * 確定 SelectionState が変わるたびに発火。ドラッグ中と初期マウントでは発火しない。明文の
1732
1822
  * ドラッグ中発火点が 1 つ: ヘッダー減算予約の実 press 変換 (初動 move) は遅延 press 置換を
1733
- * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。
1823
+ * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。ジェスチャ外のホスト起点発火点が
1824
+ * 1 つ (ADR-33): 同一 adapter の rowCount / colCount 縮小で選択が動いたとき、その commit の
1825
+ * layout effect から 1 回発火する (ユーザー操作ではない)。
1734
1826
  */
1735
1827
  onSelectionChange?: (selection: SelectionState) => void;
1736
1828
  /** Consumer context menu (§6.4.3-4 / §6.6.1 Shift+F10); keyboard origin carries the active cell viewport rect. / consumer コンテキストメニュー。 */
@@ -1834,9 +1926,11 @@ export declare type SpreadsheetProps = {
1834
1926
  enableResizeUI?: boolean;
1835
1927
  /**
1836
1928
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1837
- * 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
1838
1930
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1839
- * 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
1840
1934
  * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1841
1935
  * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1842
1936
  * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
@@ -2022,6 +2116,15 @@ declare type SpreadsheetTestProps = {
2022
2116
  * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
2023
2117
  */
2024
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;
2025
2128
  };
2026
2129
 
2027
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
@@ -1681,16 +1720,27 @@ export declare type SpreadsheetProps = {
1681
1720
  /**
1682
1721
  * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1683
1722
  * rendered beyond each vertical viewport edge. This slack is the only thing absorbing the
1684
- * engine's one-frame rendering-window lag during fast scrolling (the blank-band remedy —
1685
- * the slack in px is overscan × row height per edge). Undefined ⇒ the engine default (3).
1686
- * The engine clamps invalid values silently, so THIS surface owns the fail-fast: a
1687
- * non-integer or negative value throws a RangeError at render. Cost multiplies with the
1688
- * column axis (bounded by the engine cell cap).
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.
1689
1735
  * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1690
- * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策 —
1691
- * 余裕 px は片端あたり overscan × 行高)。undefined はエンジン既定 (3)。エンジンは不正値を
1692
- * 無言クランプするため fail-fast は本層所有 — 非整数・負値は render 時 RangeError。費用は
1693
- * 列軸との積で増幅 (エンジンのセル上限で有界)。
1736
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策)。
1737
+ * overscan は**行数**で数える (非表示の 0px 行も枠を消費) ため、片端の余裕 px が overscan ×
1738
+ * 行高になるのは行が一様に可視のときだけ。undefined はエンジン既定 (3)。エンジンは overscan を
1739
+ * 検証しない (負値は描画窓を無言で縮める) ため fail-fast は本層所有 — 非整数・負値は render 時
1740
+ * RangeError。費用は列軸との積で増幅し、エンジンは有界化でなく**打切り**で応じる: 軸毎の行予算
1741
+ * や総セル上限を超えた窓は先頭側を残し末尾側を落とす — 行予算超過はコールバック無し (エンジンは
1742
+ * warn ログのみ)、セル上限超過 (列の脱落) は `onRenderTruncated` で通知。片側数百行の値は高い viewport で予算に迫るため、必要な
1743
+ * 余裕にとどめる。
1694
1744
  */
1695
1745
  overscanRows?: number;
1696
1746
  /**
@@ -1707,18 +1757,55 @@ export declare type SpreadsheetProps = {
1707
1757
  * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1708
1758
  * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1709
1759
  * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1710
- * not to row-aligned gridlines.
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.
1711
1765
  * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1712
1766
  * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1713
1767
  * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1714
1768
  * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1715
- * 行整合の罫線には不向き。
1769
+ * 行整合の罫線には不向き。層はスクロール行の全幅 — 凍結**列**域を含む (凍結列はスクロール行の
1770
+ * 内側に居る) — に広がり、凍結行帯には広がらない。identity 安定契約 (`renderCell` と同じ):
1771
+ * インライン要素はホスト再レンダー毎に GridBody の memo 境界を貫通する (エンジンの render 本体が
1772
+ * 再実行、セルは memo 維持) — ノードは hoist するか `useMemo` で保つ。
1716
1773
  */
1717
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;
1718
1790
  /**
1719
1791
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1720
1792
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
1721
- * 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 の幅は測れない)。
1722
1809
  */
1723
1810
  renderCell?: (ctx: RenderCellContext) => ReactNode;
1724
1811
  /**
@@ -1726,11 +1813,16 @@ export declare type SpreadsheetProps = {
1726
1813
  * paste replace, Ctrl+A, ...). Never during a drag (state frozen — one fire at pointerup),
1727
1814
  * with ONE documented in-drag firing point: the header subtract reservation converts to a
1728
1815
  * real press on the first movement, firing the deferred press replace mid-drag (total fire
1729
- * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. Independent
1730
- * 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).
1731
1821
  * 確定 SelectionState が変わるたびに発火。ドラッグ中と初期マウントでは発火しない。明文の
1732
1822
  * ドラッグ中発火点が 1 つ: ヘッダー減算予約の実 press 変換 (初動 move) は遅延 press 置換を
1733
- * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。
1823
+ * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。ジェスチャ外のホスト起点発火点が
1824
+ * 1 つ (ADR-33): 同一 adapter の rowCount / colCount 縮小で選択が動いたとき、その commit の
1825
+ * layout effect から 1 回発火する (ユーザー操作ではない)。
1734
1826
  */
1735
1827
  onSelectionChange?: (selection: SelectionState) => void;
1736
1828
  /** Consumer context menu (§6.4.3-4 / §6.6.1 Shift+F10); keyboard origin carries the active cell viewport rect. / consumer コンテキストメニュー。 */
@@ -1834,9 +1926,11 @@ export declare type SpreadsheetProps = {
1834
1926
  enableResizeUI?: boolean;
1835
1927
  /**
1836
1928
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1837
- * 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
1838
1930
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1839
- * 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
1840
1934
  * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1841
1935
  * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1842
1936
  * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
@@ -2022,6 +2116,15 @@ declare type SpreadsheetTestProps = {
2022
2116
  * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
2023
2117
  */
2024
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;
2025
2128
  };
2026
2129
 
2027
2130
  export { TapScrollCircleRenderProps }