@aiquants/spreadsheet 0.9.0 → 0.11.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
@@ -2,6 +2,8 @@ import { ForwardRefExoticComponent } from 'react';
2
2
  import { ProfilerOnRenderCallback } from 'react';
3
3
  import { ReactNode } from 'react';
4
4
  import { RefAttributes } from 'react';
5
+ import { ScrollBarTapCircleOptions } from '@aiquants/virtualscroll';
6
+ import { TapScrollCircleRenderProps } from '@aiquants/virtualscroll';
5
7
 
6
8
  /** Border colour when `CellBorder.color` is absent (a stated default, not a fallback). / 罫線色の宣言済み既定 (fallback ではなく仕様上の既定)。 */
7
9
  export declare const BORDER_DEFAULT_COLOR = "#000000";
@@ -402,7 +404,7 @@ export declare const columnNameToIndex: (name: string) => number;
402
404
  */
403
405
  export declare const CommentPopover: ({ ctx, labels }: CommentPopoverProps) => ReactNode;
404
406
 
405
- /** Comment thread context: the reply UI commits `[...current (with ids), { text }]`; `null` clears the thread. / コメントスレッド文脈: 返信 UI は `[...current (id つき), { text }]` を commit、null はスレッド消去。 */
407
+ /** Comment thread context: the reply UI commits `[...current (with ids), { text }]`; `null` clears the thread. `cellReadOnly` (v0.10): same declaration-gated key as the note context. / コメントスレッド文脈: 返信 UI は `[...current (id つき), { text }]` を commit、null はスレッド消去。cellReadOnly (v0.10) は note 文脈と同じ宣言ゲートキー。 */
406
408
  export declare type CommentPopoverContext = {
407
409
  kind: "comment";
408
410
  cell: CellCoord;
@@ -411,6 +413,7 @@ export declare type CommentPopoverContext = {
411
413
  commit: (next: readonly CellCommentInput[] | null) => void;
412
414
  close: () => void;
413
415
  rejected: boolean;
416
+ cellReadOnly?: boolean;
414
417
  };
415
418
 
416
419
  export declare type CommentPopoverProps = {
@@ -480,10 +483,12 @@ export declare const DEFAULT_HIGHLIGHT_COLORS: HighlightColors;
480
483
 
481
484
  /**
482
485
  * English defaults for every key. `sinkAriaLabel` / `rootAriaLabel` are byte-identical to the
483
- * v0.7 prop defaults (the fold is DOM-identical); `noteEscapeHint` = "Escape saves and closes";
486
+ * v0.7 prop defaults (the fold is DOM-identical); `noteEscapeHint` = "Escape saves and closes"
487
+ * and its v0.10 viewer counterpart `noteViewerHint` = "Escape closes without saving";
484
488
  * `commentCount` and `listMore` pluralise ("1 comment" / "n comments", "1 more value" / "n more values"). Frozen.
485
489
  * 全キーの英語既定。`sinkAriaLabel` / `rootAriaLabel` は v0.7 の prop 既定と byte 同一 (畳込みは
486
- * DOM 恒等)、`noteEscapeHint` = "Escape saves and closes"、`commentCount` / `listMore` は単複を区別。凍結済み。
490
+ * DOM 恒等)、`noteEscapeHint` = "Escape saves and closes" とその v0.10 ビューア対応
491
+ * `noteViewerHint` = "Escape closes without saving"、`commentCount` / `listMore` は単複を区別。凍結済み。
487
492
  */
488
493
  export declare const DEFAULT_LABELS: SpreadsheetLabels;
489
494
 
@@ -680,7 +685,7 @@ export declare type HtmlTableResult = {
680
685
  */
681
686
  export declare const LinkPopover: ({ ctx, labels }: LinkPopoverProps) => ReactNode;
682
687
 
683
- /** Hyperlink editor context: `url` on commit is a normalised href or null (clear); `canOpen` = onHyperlinkOpen declared. / ハイパーリンクエディタ文脈: commit の url は正規化済み href か null (消去)、canOpen = onHyperlinkOpen 宣言。 */
688
+ /** Hyperlink editor context: `url` on commit is a normalised href or null (clear); `canOpen` = onHyperlinkOpen declared. `cellReadOnly` (v0.10): same declaration-gated key as the note context (the Open button stays live — navigation is a read). / ハイパーリンクエディタ文脈: commit の url は正規化済み href か null (消去)、canOpen = onHyperlinkOpen 宣言。cellReadOnly (v0.10) は note 文脈と同じ宣言ゲートキー (Open は読みなので生きたまま)。 */
684
689
  export declare type LinkPopoverContext = {
685
690
  kind: "link";
686
691
  cell: CellCoord;
@@ -697,6 +702,7 @@ export declare type LinkPopoverContext = {
697
702
  canOpen: boolean;
698
703
  open: () => void;
699
704
  rejected: boolean;
705
+ cellReadOnly?: boolean;
700
706
  };
701
707
 
702
708
  export declare type LinkPopoverProps = {
@@ -796,7 +802,7 @@ export declare type NotEmptyCondition = {
796
802
  */
797
803
  export declare const NotePopover: ({ ctx, labels }: NotePopoverProps) => ReactNode;
798
804
 
799
- /** Note editor context (v0.8 §1.8). `current` undefined = no note yet; `commit(null)` clears. / note エディタ文脈。current undefined = ノートなし、commit(null) は消去。 */
805
+ /** Note editor context (v0.8 §1.8). `current` undefined = no note yet; `commit(null)` clears. `cellReadOnly` (v0.10, declaration-gated): key ABSENT = the `isCellReadOnly` capability is undeclared (byte-identical context), else the live predicate answer — `true` disables the default component's commit affordance (G14a walls the commit regardless). / note エディタ文脈。current undefined = ノートなし、commit(null) は消去。cellReadOnly (v0.10、宣言ゲート): キー不在 = isCellReadOnly 能力未宣言 (context はバイト恒等)、あれば live 述語の答え — true は既定コンポーネントの確定操作を disabled にする (壁は G14a)。 */
800
806
  export declare type NotePopoverContext = {
801
807
  kind: "note";
802
808
  cell: CellCoord;
@@ -805,6 +811,7 @@ export declare type NotePopoverContext = {
805
811
  commit: (next: string | null) => void;
806
812
  close: () => void;
807
813
  rejected: boolean;
814
+ cellReadOnly?: boolean;
808
815
  };
809
816
 
810
817
  export declare type NotePopoverProps = {
@@ -1006,6 +1013,36 @@ export declare const rangeSize: (range: CellRange) => {
1006
1013
  cols: number;
1007
1014
  };
1008
1015
 
1016
+ /**
1017
+ * Context of a READ-ONLY refusal (v0.10, delivered by onReadOnlyRejected): fired once per
1018
+ * refused gesture — the adapter was never called, so this is neither an {@link EditRejection}
1019
+ * (applyEdits never threw) nor an operation limit. `kind: "edit"` is a refused single-cell
1020
+ * text-write entry or commit and carries the cell; `kind: "operation"` is a refused whole
1021
+ * operation with its producer's own overlap-naive `cellCount` arithmetic (the same numbers the
1022
+ * limit channel reports — never a dedup count).
1023
+ * 読み取り専用拒否の文脈 (v0.10 — onReadOnlyRejected が届ける): 拒否されたジェスチャ毎に 1 回
1024
+ * 発火。adapter は呼ばれていないため {@link EditRejection} (applyEdits の throw) でも操作上限
1025
+ * でもない。`kind: "edit"` はセル単位テキスト書込の入口 / 確定の拒否でセル座標を運び、
1026
+ * `kind: "operation"` は操作全体の拒否で、`cellCount` はプロデューサ自身の overlap-naive 算術
1027
+ * (上限チャネルと同じ数 — dedup 数ではない)。
1028
+ */
1029
+ export declare type ReadOnlyRejection = {
1030
+ readonly kind: "edit";
1031
+ readonly cell: CellCoord;
1032
+ /**
1033
+ * Fate of the edit session THIS refusal adjudicated: "none" = no session commit was
1034
+ * adjudicated (no session existed at the refusing gate, or the gate does not commit
1035
+ * sessions — an untouched session may still exist, e.g. the G15 list chord during a
1036
+ * flipped session); "kept" / "discarded" = G16's caller-declared fate.
1037
+ * この拒否が裁いた編集セッションの帰結。none = セッション確定を裁いていない。
1038
+ */
1039
+ readonly editSession: "none" | "kept" | "discarded";
1040
+ } | {
1041
+ readonly kind: "operation";
1042
+ readonly op: "cut" | "delete" | "paste" | "fill" | "format" | "calc" | "annotate";
1043
+ readonly cellCount: number;
1044
+ };
1045
+
1009
1046
  /** Public custom cell renderer context (ADR-8). / 公開セルレンダラーの ctx (ADR-8)。 */
1010
1047
  export declare type RenderCellContext = {
1011
1048
  row: number;
@@ -1028,6 +1065,8 @@ export declare type ScalePoint = {
1028
1065
  value?: number;
1029
1066
  };
1030
1067
 
1068
+ export { ScrollBarTapCircleOptions }
1069
+
1031
1070
  /**
1032
1071
  * Options for the programmatic {@link SpreadsheetHandle.scrollToCell} jump — the render-surface
1033
1072
  * pass-through of the engine's cell-targeted scroll (alignX uses start/end/center, alignY uses
@@ -1349,6 +1388,21 @@ export declare type SpreadsheetDataAdapter = {
1349
1388
  * PasteEditContext.conditionalFormats で届く)。未宣言 = base 書式をそのまま塗る。
1350
1389
  */
1351
1390
  getConditionalFormats?: () => readonly ConditionalFormatRule[];
1391
+ /**
1392
+ * Read-only declaration for one cell (v0.10 read-only cells). `true` = the cell can never be
1393
+ * written by this grid: edit-mode entry is refused, an already-open session's commit re-checks
1394
+ * this predicate live, and every write operation whose target set contains the cell is rejected
1395
+ * WHOLE before the adapter is called. Consulted live per gesture (never memoised); publish
1396
+ * changes via `dataVersion`. The grid only ever calls this with in-grid coordinates. Host cost
1397
+ * budget: O(1) and allocation-free — the same budget as `getCellText` (it also runs once per
1398
+ * painted read-only-capable cell). Absence = every cell editable = the previous version's
1399
+ * behaviour byte-identically.
1400
+ * 読み取り専用宣言 (v0.10)。true のセルは編集モードに入れず、開いているセッションの確定も
1401
+ * ライブ再検査され、対象に含む書込操作は adapter 到達前に全体拒否。ジェスチャ毎に生読み、
1402
+ * 変更は dataVersion で公開。座標は常にグリッド内。ホスト側コストは O(1)・割当なし
1403
+ * (getCellText と同格、描画パスでも呼ばれるため)。未宣言 = 全セル編集可 = 従来挙動とバイト同一。
1404
+ */
1405
+ isCellReadOnly?: (row: number, col: number) => boolean;
1352
1406
  /**
1353
1407
  * OPTIONAL capability (v0.8): the numeric minimum / maximum over a range, for colorScale
1354
1408
  * rules whose end points omit `value`; null = the range holds no numeric value. Memoised by
@@ -1488,6 +1542,8 @@ export declare type SpreadsheetLabels = {
1488
1542
  noteEscapeHint: string;
1489
1543
  /** Note popover hint in the rejected state (Ctrl+Enter retries, Escape closes without saving). / 拒否状態のノートヒント。 */
1490
1544
  noteRejectedHint: string;
1545
+ /** Note popover hint in the v0.10 read-only viewer mode (Escape closes without saving — the commit affordance is disabled, so the hint must not promise a save). / 読み取り専用ビューアモード (v0.10) のノートヒント (Escape は保存せず閉じる — 確定操作は disabled のため保存を約束しない)。 */
1546
+ noteViewerHint: string;
1491
1547
  /** Comment popover heading. / コメントポップオーバーの見出し。 */
1492
1548
  commentTitle: string;
1493
1549
  /** Comment reply field label. / 返信入力欄のラベル。 */
@@ -1610,6 +1666,55 @@ export declare type SpreadsheetProps = {
1610
1666
  * frozenTrailingColumns の行双子。エンジン契約・取消シームは同文)。典型は固定合計行。
1611
1667
  */
1612
1668
  frozenTrailingRows?: number;
1669
+ /**
1670
+ * Tap-scroll circle tuning (v0.10 — the VirtualGrid `scrollBarOptions.tapScrollCircleOptions`
1671
+ * engine-validated pass-through; LIVE prop): position and enable/disable of the touch
1672
+ * tap-scroll circle. The engine's `resolveTapScrollCircleOptions` is the validation SSOT —
1673
+ * undefined is the engine's declared absence signal (engine defaults), never a value
1674
+ * fallback in this package.
1675
+ * タップサークル調整 (v0.10 — VirtualGrid `scrollBarOptions.tapScrollCircleOptions` の
1676
+ * エンジン検証素通し。ライブ prop): タッチのタップスクロールサークルの位置・有効 / 無効の
1677
+ * 調整口。検証の SSOT はエンジンの `resolveTapScrollCircleOptions` — undefined はエンジン
1678
+ * 宣言の不在信号 (エンジン既定) で、本パッケージでの値フォールバックなし。
1679
+ */
1680
+ tapScrollCircleOptions?: ScrollBarTapCircleOptions;
1681
+ /**
1682
+ * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1683
+ * 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).
1689
+ * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1690
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策 —
1691
+ * 余裕 px は片端あたり overscan × 行高)。undefined はエンジン既定 (3)。エンジンは不正値を
1692
+ * 無言クランプするため fail-fast は本層所有 — 非整数・負値は render 時 RangeError。費用は
1693
+ * 列軸との積で増幅 (エンジンのセル上限で有界)。
1694
+ */
1695
+ overscanRows?: number;
1696
+ /**
1697
+ * Column-axis overscan pass-through (the VirtualGrid `overscanCols` knob; LIVE prop) — the
1698
+ * column twin of `overscanRows`, same validation contract (non-negative integer or
1699
+ * RangeError; undefined ⇒ engine default 3).
1700
+ * 列軸 overscan の素通し (VirtualGrid `overscanCols`。ライブ prop) — `overscanRows` の
1701
+ * 列双子。検証契約は同文 (非負整数、それ以外 RangeError。undefined ⇒ エンジン既定 3)。
1702
+ */
1703
+ overscanCols?: number;
1704
+ /**
1705
+ * Background layer rendered behind the scroll-band rows, inside the engine content element
1706
+ * (the VirtualGrid `background` pass-through; LIVE prop). VIEWPORT-PINNED: the engine
1707
+ * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1708
+ * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1709
+ * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1710
+ * not to row-aligned gridlines.
1711
+ * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1712
+ * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1713
+ * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1714
+ * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1715
+ * 行整合の罫線には不向き。
1716
+ */
1717
+ background?: ReactNode;
1613
1718
  /**
1614
1719
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1615
1720
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
@@ -1672,6 +1777,39 @@ export declare type SpreadsheetProps = {
1672
1777
  * Escape は WCAG 2.1.2 のフォーカス脱出)。
1673
1778
  */
1674
1779
  onEditRejected?: (error: unknown, rejection: EditRejection) => void;
1780
+ /**
1781
+ * Read-only refusal notice (v0.10): fired once per refused gesture — the adapter was never
1782
+ * called, so this is neither an EditRejection nor an operation limit. Never fired when the
1783
+ * adapter does not declare `isCellReadOnly`; omit for silence.
1784
+ * 読み取り専用拒否通知 (v0.10)。拒否されたジェスチャ毎に 1 回発火 — adapter は呼ばれて
1785
+ * いないため EditRejection でも操作上限でもない。`isCellReadOnly` 未宣言では発火せず、
1786
+ * 省略時は通知なし。
1787
+ */
1788
+ onReadOnlyRejected?: (rejection: ReadOnlyRejection) => void;
1789
+ /**
1790
+ * AT announcement text for a read-only refusal (v0.10), routed through the live region;
1791
+ * omit for silence (no built-in strings). Inherits the announcement debounce + rAF collapse,
1792
+ * which is what keeps autorepeat / IME refusal storms from spamming the live region.
1793
+ * 読み取り専用拒否の AT 読み上げ文言 (v0.10) — live region 経由。省略で無音 (組み込み文言
1794
+ * なし)。読み上げのデバウンス + rAF 合流を継承し、autorepeat / IME の拒否連打でも live
1795
+ * region は溢れない。
1796
+ */
1797
+ formatReadOnlyAnnouncement?: (rejection: ReadOnlyRejection) => string;
1798
+ /**
1799
+ * Paste outcome summary (v0.10 plan §3.1): the menu channel mirrors `paste(options)`'s
1800
+ * resolve value 1:1 (read refusals and the write-time re-gate included); the event channel
1801
+ * fires once per gesture that reaches the paste pipeline — the drag-freeze consumption and a
1802
+ * null `clipboardData` stay deliberately silent, and an empty grid attaches no listener at
1803
+ * all. Cause-specific callbacks (`onClipboardUnavailable` / `onOperationRejected` /
1804
+ * `onReadOnlyRejected`) fire FIRST — `"rejected"` can be the trailing summary of one of
1805
+ * them. Omit = never fired.
1806
+ * 貼り付け結果の要約 (v0.10 計画 §3.1)。menu チャネルは `paste(options)` の resolve 値の
1807
+ * 1:1 鏡 (読み拒否・書込時再ゲート含む)、event チャネルは貼り付けパイプラインに到達した
1808
+ * ゲスチャ毎 1 回 — ドラッグ凍結消費と `clipboardData` null は意図的無言、空グリッドは
1809
+ * リスナ自体が無い。原因特定系 callback が先に発火し、`"rejected"` はその後追いの要約に
1810
+ * なり得る。省略時は発火なし。
1811
+ */
1812
+ onPasteResolved?: (outcome: PasteOutcome, channel: ClipChannel) => void;
1675
1813
  /** Change notice for out-of-package writes (undo / collaboration); each increment repaints visible cells (§6.9-2). / パッケージ外経路のデータ変更通知。 */
1676
1814
  dataVersion?: number;
1677
1815
  /** Operation cell-count ceiling, default 100,000 (ADR-12). / 操作セル数上限。 */
@@ -1698,10 +1836,17 @@ export declare type SpreadsheetProps = {
1698
1836
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1699
1837
  * is the RAW canonical getCellText; `displayText` is what a sighted user sees (the
1700
1838
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1701
- * hear "87.0%" for a cell whose raw value is "0.87".
1839
+ * hear "87.0%" for a cell whose raw value is "0.87". `readOnly` (v0.10) is
1840
+ * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1841
+ * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1842
+ * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
1843
+ * so `aria-readonly` is inert during Arrow navigation).
1702
1844
  * AT 向け読み上げ文言 (省略で無音)。`text` は素の正準 getCellText、`displayText` は目視と同じ
1703
1845
  * 表示文字列 (getCellFormat 整形後 — 書式なしセルでは text と同値)。素値 "0.87" の表示
1704
- * "87.0%" をそのまま読み上げられる。
1846
+ * "87.0%" をそのまま読み上げられる。`readOnly` (v0.10) は宣言ゲートの 3 値: `isCellReadOnly`
1847
+ * 未宣言はキー自体なし (payload は v0.9 とバイト同一)、`false` = 宣言済み編集可、`true` =
1848
+ * 宣言済み読み取り専用 — 矢印航行時の読み取り専用チャネル (フォーカスはシンク常駐のため
1849
+ * `aria-readonly` は航行中の AT に届かない)。
1705
1850
  */
1706
1851
  formatCellAnnouncement?: (ctx: {
1707
1852
  row: number;
@@ -1709,6 +1854,7 @@ export declare type SpreadsheetProps = {
1709
1854
  text: string;
1710
1855
  displayText: string;
1711
1856
  columnName: string;
1857
+ readOnly?: boolean;
1712
1858
  }) => string;
1713
1859
  /** AT announcement for the selection extent ("A1 to C3, 3 rows 3 cols"); omit for silence. / AT 向け選択範囲読み上げ。 */
1714
1860
  formatSelectionAnnouncement?: (ctx: {
@@ -1865,8 +2011,21 @@ export declare type SpreadsheetProps = {
1865
2011
  declare type SpreadsheetTestProps = {
1866
2012
  /** Test-only CellView re-render counter; never passed in production. / テスト専用カウンタ。 */
1867
2013
  __onCellRender?: ProfilerOnRenderCallback;
2014
+ /**
2015
+ * Test-only virtual-keyboard raise spy (v0.10 plan §6.4 / RC-G2t): called synchronously by
2016
+ * the single `raiseVirtualKeyboard` funnel, so spy count ≡ raise executions — a React-batched
2017
+ * raise-then-lower mutates no DOM (`inputmode` observer-blind) yet still counts. Never
2018
+ * passed in production (zero calls when unset — the `__onCellRender` conduct).
2019
+ * テスト専用の仮想キーボード招待スパイ (v0.10 計画 §6.4 / RC-G2t)。単一漏斗
2020
+ * `raiseVirtualKeyboard` が同期で呼ぶため、計数 ≡ raise 実行 — React バッチの
2021
+ * raise-then-lower は DOM 無変異 (`inputmode` の観測は盲目) でも計数には映る。production
2022
+ * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
2023
+ */
2024
+ __onVirtualKeyboardRaise?: () => void;
1868
2025
  };
1869
2026
 
2027
+ export { TapScrollCircleRenderProps }
2028
+
1870
2029
  /** Case-sensitive needle test on the raw text. / 素の text に対する大文字小文字区別の needle 判定。 */
1871
2030
  export declare type TextCondition = {
1872
2031
  type: "text";
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ import { ForwardRefExoticComponent } from 'react';
2
2
  import { ProfilerOnRenderCallback } from 'react';
3
3
  import { ReactNode } from 'react';
4
4
  import { RefAttributes } from 'react';
5
+ import { ScrollBarTapCircleOptions } from '@aiquants/virtualscroll';
6
+ import { TapScrollCircleRenderProps } from '@aiquants/virtualscroll';
5
7
 
6
8
  /** Border colour when `CellBorder.color` is absent (a stated default, not a fallback). / 罫線色の宣言済み既定 (fallback ではなく仕様上の既定)。 */
7
9
  export declare const BORDER_DEFAULT_COLOR = "#000000";
@@ -402,7 +404,7 @@ export declare const columnNameToIndex: (name: string) => number;
402
404
  */
403
405
  export declare const CommentPopover: ({ ctx, labels }: CommentPopoverProps) => ReactNode;
404
406
 
405
- /** Comment thread context: the reply UI commits `[...current (with ids), { text }]`; `null` clears the thread. / コメントスレッド文脈: 返信 UI は `[...current (id つき), { text }]` を commit、null はスレッド消去。 */
407
+ /** Comment thread context: the reply UI commits `[...current (with ids), { text }]`; `null` clears the thread. `cellReadOnly` (v0.10): same declaration-gated key as the note context. / コメントスレッド文脈: 返信 UI は `[...current (id つき), { text }]` を commit、null はスレッド消去。cellReadOnly (v0.10) は note 文脈と同じ宣言ゲートキー。 */
406
408
  export declare type CommentPopoverContext = {
407
409
  kind: "comment";
408
410
  cell: CellCoord;
@@ -411,6 +413,7 @@ export declare type CommentPopoverContext = {
411
413
  commit: (next: readonly CellCommentInput[] | null) => void;
412
414
  close: () => void;
413
415
  rejected: boolean;
416
+ cellReadOnly?: boolean;
414
417
  };
415
418
 
416
419
  export declare type CommentPopoverProps = {
@@ -480,10 +483,12 @@ export declare const DEFAULT_HIGHLIGHT_COLORS: HighlightColors;
480
483
 
481
484
  /**
482
485
  * English defaults for every key. `sinkAriaLabel` / `rootAriaLabel` are byte-identical to the
483
- * v0.7 prop defaults (the fold is DOM-identical); `noteEscapeHint` = "Escape saves and closes";
486
+ * v0.7 prop defaults (the fold is DOM-identical); `noteEscapeHint` = "Escape saves and closes"
487
+ * and its v0.10 viewer counterpart `noteViewerHint` = "Escape closes without saving";
484
488
  * `commentCount` and `listMore` pluralise ("1 comment" / "n comments", "1 more value" / "n more values"). Frozen.
485
489
  * 全キーの英語既定。`sinkAriaLabel` / `rootAriaLabel` は v0.7 の prop 既定と byte 同一 (畳込みは
486
- * DOM 恒等)、`noteEscapeHint` = "Escape saves and closes"、`commentCount` / `listMore` は単複を区別。凍結済み。
490
+ * DOM 恒等)、`noteEscapeHint` = "Escape saves and closes" とその v0.10 ビューア対応
491
+ * `noteViewerHint` = "Escape closes without saving"、`commentCount` / `listMore` は単複を区別。凍結済み。
487
492
  */
488
493
  export declare const DEFAULT_LABELS: SpreadsheetLabels;
489
494
 
@@ -680,7 +685,7 @@ export declare type HtmlTableResult = {
680
685
  */
681
686
  export declare const LinkPopover: ({ ctx, labels }: LinkPopoverProps) => ReactNode;
682
687
 
683
- /** Hyperlink editor context: `url` on commit is a normalised href or null (clear); `canOpen` = onHyperlinkOpen declared. / ハイパーリンクエディタ文脈: commit の url は正規化済み href か null (消去)、canOpen = onHyperlinkOpen 宣言。 */
688
+ /** Hyperlink editor context: `url` on commit is a normalised href or null (clear); `canOpen` = onHyperlinkOpen declared. `cellReadOnly` (v0.10): same declaration-gated key as the note context (the Open button stays live — navigation is a read). / ハイパーリンクエディタ文脈: commit の url は正規化済み href か null (消去)、canOpen = onHyperlinkOpen 宣言。cellReadOnly (v0.10) は note 文脈と同じ宣言ゲートキー (Open は読みなので生きたまま)。 */
684
689
  export declare type LinkPopoverContext = {
685
690
  kind: "link";
686
691
  cell: CellCoord;
@@ -697,6 +702,7 @@ export declare type LinkPopoverContext = {
697
702
  canOpen: boolean;
698
703
  open: () => void;
699
704
  rejected: boolean;
705
+ cellReadOnly?: boolean;
700
706
  };
701
707
 
702
708
  export declare type LinkPopoverProps = {
@@ -796,7 +802,7 @@ export declare type NotEmptyCondition = {
796
802
  */
797
803
  export declare const NotePopover: ({ ctx, labels }: NotePopoverProps) => ReactNode;
798
804
 
799
- /** Note editor context (v0.8 §1.8). `current` undefined = no note yet; `commit(null)` clears. / note エディタ文脈。current undefined = ノートなし、commit(null) は消去。 */
805
+ /** Note editor context (v0.8 §1.8). `current` undefined = no note yet; `commit(null)` clears. `cellReadOnly` (v0.10, declaration-gated): key ABSENT = the `isCellReadOnly` capability is undeclared (byte-identical context), else the live predicate answer — `true` disables the default component's commit affordance (G14a walls the commit regardless). / note エディタ文脈。current undefined = ノートなし、commit(null) は消去。cellReadOnly (v0.10、宣言ゲート): キー不在 = isCellReadOnly 能力未宣言 (context はバイト恒等)、あれば live 述語の答え — true は既定コンポーネントの確定操作を disabled にする (壁は G14a)。 */
800
806
  export declare type NotePopoverContext = {
801
807
  kind: "note";
802
808
  cell: CellCoord;
@@ -805,6 +811,7 @@ export declare type NotePopoverContext = {
805
811
  commit: (next: string | null) => void;
806
812
  close: () => void;
807
813
  rejected: boolean;
814
+ cellReadOnly?: boolean;
808
815
  };
809
816
 
810
817
  export declare type NotePopoverProps = {
@@ -1006,6 +1013,36 @@ export declare const rangeSize: (range: CellRange) => {
1006
1013
  cols: number;
1007
1014
  };
1008
1015
 
1016
+ /**
1017
+ * Context of a READ-ONLY refusal (v0.10, delivered by onReadOnlyRejected): fired once per
1018
+ * refused gesture — the adapter was never called, so this is neither an {@link EditRejection}
1019
+ * (applyEdits never threw) nor an operation limit. `kind: "edit"` is a refused single-cell
1020
+ * text-write entry or commit and carries the cell; `kind: "operation"` is a refused whole
1021
+ * operation with its producer's own overlap-naive `cellCount` arithmetic (the same numbers the
1022
+ * limit channel reports — never a dedup count).
1023
+ * 読み取り専用拒否の文脈 (v0.10 — onReadOnlyRejected が届ける): 拒否されたジェスチャ毎に 1 回
1024
+ * 発火。adapter は呼ばれていないため {@link EditRejection} (applyEdits の throw) でも操作上限
1025
+ * でもない。`kind: "edit"` はセル単位テキスト書込の入口 / 確定の拒否でセル座標を運び、
1026
+ * `kind: "operation"` は操作全体の拒否で、`cellCount` はプロデューサ自身の overlap-naive 算術
1027
+ * (上限チャネルと同じ数 — dedup 数ではない)。
1028
+ */
1029
+ export declare type ReadOnlyRejection = {
1030
+ readonly kind: "edit";
1031
+ readonly cell: CellCoord;
1032
+ /**
1033
+ * Fate of the edit session THIS refusal adjudicated: "none" = no session commit was
1034
+ * adjudicated (no session existed at the refusing gate, or the gate does not commit
1035
+ * sessions — an untouched session may still exist, e.g. the G15 list chord during a
1036
+ * flipped session); "kept" / "discarded" = G16's caller-declared fate.
1037
+ * この拒否が裁いた編集セッションの帰結。none = セッション確定を裁いていない。
1038
+ */
1039
+ readonly editSession: "none" | "kept" | "discarded";
1040
+ } | {
1041
+ readonly kind: "operation";
1042
+ readonly op: "cut" | "delete" | "paste" | "fill" | "format" | "calc" | "annotate";
1043
+ readonly cellCount: number;
1044
+ };
1045
+
1009
1046
  /** Public custom cell renderer context (ADR-8). / 公開セルレンダラーの ctx (ADR-8)。 */
1010
1047
  export declare type RenderCellContext = {
1011
1048
  row: number;
@@ -1028,6 +1065,8 @@ export declare type ScalePoint = {
1028
1065
  value?: number;
1029
1066
  };
1030
1067
 
1068
+ export { ScrollBarTapCircleOptions }
1069
+
1031
1070
  /**
1032
1071
  * Options for the programmatic {@link SpreadsheetHandle.scrollToCell} jump — the render-surface
1033
1072
  * pass-through of the engine's cell-targeted scroll (alignX uses start/end/center, alignY uses
@@ -1349,6 +1388,21 @@ export declare type SpreadsheetDataAdapter = {
1349
1388
  * PasteEditContext.conditionalFormats で届く)。未宣言 = base 書式をそのまま塗る。
1350
1389
  */
1351
1390
  getConditionalFormats?: () => readonly ConditionalFormatRule[];
1391
+ /**
1392
+ * Read-only declaration for one cell (v0.10 read-only cells). `true` = the cell can never be
1393
+ * written by this grid: edit-mode entry is refused, an already-open session's commit re-checks
1394
+ * this predicate live, and every write operation whose target set contains the cell is rejected
1395
+ * WHOLE before the adapter is called. Consulted live per gesture (never memoised); publish
1396
+ * changes via `dataVersion`. The grid only ever calls this with in-grid coordinates. Host cost
1397
+ * budget: O(1) and allocation-free — the same budget as `getCellText` (it also runs once per
1398
+ * painted read-only-capable cell). Absence = every cell editable = the previous version's
1399
+ * behaviour byte-identically.
1400
+ * 読み取り専用宣言 (v0.10)。true のセルは編集モードに入れず、開いているセッションの確定も
1401
+ * ライブ再検査され、対象に含む書込操作は adapter 到達前に全体拒否。ジェスチャ毎に生読み、
1402
+ * 変更は dataVersion で公開。座標は常にグリッド内。ホスト側コストは O(1)・割当なし
1403
+ * (getCellText と同格、描画パスでも呼ばれるため)。未宣言 = 全セル編集可 = 従来挙動とバイト同一。
1404
+ */
1405
+ isCellReadOnly?: (row: number, col: number) => boolean;
1352
1406
  /**
1353
1407
  * OPTIONAL capability (v0.8): the numeric minimum / maximum over a range, for colorScale
1354
1408
  * rules whose end points omit `value`; null = the range holds no numeric value. Memoised by
@@ -1488,6 +1542,8 @@ export declare type SpreadsheetLabels = {
1488
1542
  noteEscapeHint: string;
1489
1543
  /** Note popover hint in the rejected state (Ctrl+Enter retries, Escape closes without saving). / 拒否状態のノートヒント。 */
1490
1544
  noteRejectedHint: string;
1545
+ /** Note popover hint in the v0.10 read-only viewer mode (Escape closes without saving — the commit affordance is disabled, so the hint must not promise a save). / 読み取り専用ビューアモード (v0.10) のノートヒント (Escape は保存せず閉じる — 確定操作は disabled のため保存を約束しない)。 */
1546
+ noteViewerHint: string;
1491
1547
  /** Comment popover heading. / コメントポップオーバーの見出し。 */
1492
1548
  commentTitle: string;
1493
1549
  /** Comment reply field label. / 返信入力欄のラベル。 */
@@ -1610,6 +1666,55 @@ export declare type SpreadsheetProps = {
1610
1666
  * frozenTrailingColumns の行双子。エンジン契約・取消シームは同文)。典型は固定合計行。
1611
1667
  */
1612
1668
  frozenTrailingRows?: number;
1669
+ /**
1670
+ * Tap-scroll circle tuning (v0.10 — the VirtualGrid `scrollBarOptions.tapScrollCircleOptions`
1671
+ * engine-validated pass-through; LIVE prop): position and enable/disable of the touch
1672
+ * tap-scroll circle. The engine's `resolveTapScrollCircleOptions` is the validation SSOT —
1673
+ * undefined is the engine's declared absence signal (engine defaults), never a value
1674
+ * fallback in this package.
1675
+ * タップサークル調整 (v0.10 — VirtualGrid `scrollBarOptions.tapScrollCircleOptions` の
1676
+ * エンジン検証素通し。ライブ prop): タッチのタップスクロールサークルの位置・有効 / 無効の
1677
+ * 調整口。検証の SSOT はエンジンの `resolveTapScrollCircleOptions` — undefined はエンジン
1678
+ * 宣言の不在信号 (エンジン既定) で、本パッケージでの値フォールバックなし。
1679
+ */
1680
+ tapScrollCircleOptions?: ScrollBarTapCircleOptions;
1681
+ /**
1682
+ * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1683
+ * 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).
1689
+ * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1690
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策 —
1691
+ * 余裕 px は片端あたり overscan × 行高)。undefined はエンジン既定 (3)。エンジンは不正値を
1692
+ * 無言クランプするため fail-fast は本層所有 — 非整数・負値は render 時 RangeError。費用は
1693
+ * 列軸との積で増幅 (エンジンのセル上限で有界)。
1694
+ */
1695
+ overscanRows?: number;
1696
+ /**
1697
+ * Column-axis overscan pass-through (the VirtualGrid `overscanCols` knob; LIVE prop) — the
1698
+ * column twin of `overscanRows`, same validation contract (non-negative integer or
1699
+ * RangeError; undefined ⇒ engine default 3).
1700
+ * 列軸 overscan の素通し (VirtualGrid `overscanCols`。ライブ prop) — `overscanRows` の
1701
+ * 列双子。検証契約は同文 (非負整数、それ以外 RangeError。undefined ⇒ エンジン既定 3)。
1702
+ */
1703
+ overscanCols?: number;
1704
+ /**
1705
+ * Background layer rendered behind the scroll-band rows, inside the engine content element
1706
+ * (the VirtualGrid `background` pass-through; LIVE prop). VIEWPORT-PINNED: the engine
1707
+ * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1708
+ * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1709
+ * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1710
+ * not to row-aligned gridlines.
1711
+ * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1712
+ * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1713
+ * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1714
+ * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1715
+ * 行整合の罫線には不向き。
1716
+ */
1717
+ background?: ReactNode;
1613
1718
  /**
1614
1719
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1615
1720
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
@@ -1672,6 +1777,39 @@ export declare type SpreadsheetProps = {
1672
1777
  * Escape は WCAG 2.1.2 のフォーカス脱出)。
1673
1778
  */
1674
1779
  onEditRejected?: (error: unknown, rejection: EditRejection) => void;
1780
+ /**
1781
+ * Read-only refusal notice (v0.10): fired once per refused gesture — the adapter was never
1782
+ * called, so this is neither an EditRejection nor an operation limit. Never fired when the
1783
+ * adapter does not declare `isCellReadOnly`; omit for silence.
1784
+ * 読み取り専用拒否通知 (v0.10)。拒否されたジェスチャ毎に 1 回発火 — adapter は呼ばれて
1785
+ * いないため EditRejection でも操作上限でもない。`isCellReadOnly` 未宣言では発火せず、
1786
+ * 省略時は通知なし。
1787
+ */
1788
+ onReadOnlyRejected?: (rejection: ReadOnlyRejection) => void;
1789
+ /**
1790
+ * AT announcement text for a read-only refusal (v0.10), routed through the live region;
1791
+ * omit for silence (no built-in strings). Inherits the announcement debounce + rAF collapse,
1792
+ * which is what keeps autorepeat / IME refusal storms from spamming the live region.
1793
+ * 読み取り専用拒否の AT 読み上げ文言 (v0.10) — live region 経由。省略で無音 (組み込み文言
1794
+ * なし)。読み上げのデバウンス + rAF 合流を継承し、autorepeat / IME の拒否連打でも live
1795
+ * region は溢れない。
1796
+ */
1797
+ formatReadOnlyAnnouncement?: (rejection: ReadOnlyRejection) => string;
1798
+ /**
1799
+ * Paste outcome summary (v0.10 plan §3.1): the menu channel mirrors `paste(options)`'s
1800
+ * resolve value 1:1 (read refusals and the write-time re-gate included); the event channel
1801
+ * fires once per gesture that reaches the paste pipeline — the drag-freeze consumption and a
1802
+ * null `clipboardData` stay deliberately silent, and an empty grid attaches no listener at
1803
+ * all. Cause-specific callbacks (`onClipboardUnavailable` / `onOperationRejected` /
1804
+ * `onReadOnlyRejected`) fire FIRST — `"rejected"` can be the trailing summary of one of
1805
+ * them. Omit = never fired.
1806
+ * 貼り付け結果の要約 (v0.10 計画 §3.1)。menu チャネルは `paste(options)` の resolve 値の
1807
+ * 1:1 鏡 (読み拒否・書込時再ゲート含む)、event チャネルは貼り付けパイプラインに到達した
1808
+ * ゲスチャ毎 1 回 — ドラッグ凍結消費と `clipboardData` null は意図的無言、空グリッドは
1809
+ * リスナ自体が無い。原因特定系 callback が先に発火し、`"rejected"` はその後追いの要約に
1810
+ * なり得る。省略時は発火なし。
1811
+ */
1812
+ onPasteResolved?: (outcome: PasteOutcome, channel: ClipChannel) => void;
1675
1813
  /** Change notice for out-of-package writes (undo / collaboration); each increment repaints visible cells (§6.9-2). / パッケージ外経路のデータ変更通知。 */
1676
1814
  dataVersion?: number;
1677
1815
  /** Operation cell-count ceiling, default 100,000 (ADR-12). / 操作セル数上限。 */
@@ -1698,10 +1836,17 @@ export declare type SpreadsheetProps = {
1698
1836
  * AT announcement text for the active cell; omit for silence (no built-in strings). `text`
1699
1837
  * is the RAW canonical getCellText; `displayText` is what a sighted user sees (the
1700
1838
  * getCellFormat-formatted string — equals `text` when the cell has no format), so AT can
1701
- * hear "87.0%" for a cell whose raw value is "0.87".
1839
+ * hear "87.0%" for a cell whose raw value is "0.87". `readOnly` (v0.10) is
1840
+ * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1841
+ * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1842
+ * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
1843
+ * so `aria-readonly` is inert during Arrow navigation).
1702
1844
  * AT 向け読み上げ文言 (省略で無音)。`text` は素の正準 getCellText、`displayText` は目視と同じ
1703
1845
  * 表示文字列 (getCellFormat 整形後 — 書式なしセルでは text と同値)。素値 "0.87" の表示
1704
- * "87.0%" をそのまま読み上げられる。
1846
+ * "87.0%" をそのまま読み上げられる。`readOnly` (v0.10) は宣言ゲートの 3 値: `isCellReadOnly`
1847
+ * 未宣言はキー自体なし (payload は v0.9 とバイト同一)、`false` = 宣言済み編集可、`true` =
1848
+ * 宣言済み読み取り専用 — 矢印航行時の読み取り専用チャネル (フォーカスはシンク常駐のため
1849
+ * `aria-readonly` は航行中の AT に届かない)。
1705
1850
  */
1706
1851
  formatCellAnnouncement?: (ctx: {
1707
1852
  row: number;
@@ -1709,6 +1854,7 @@ export declare type SpreadsheetProps = {
1709
1854
  text: string;
1710
1855
  displayText: string;
1711
1856
  columnName: string;
1857
+ readOnly?: boolean;
1712
1858
  }) => string;
1713
1859
  /** AT announcement for the selection extent ("A1 to C3, 3 rows 3 cols"); omit for silence. / AT 向け選択範囲読み上げ。 */
1714
1860
  formatSelectionAnnouncement?: (ctx: {
@@ -1865,8 +2011,21 @@ export declare type SpreadsheetProps = {
1865
2011
  declare type SpreadsheetTestProps = {
1866
2012
  /** Test-only CellView re-render counter; never passed in production. / テスト専用カウンタ。 */
1867
2013
  __onCellRender?: ProfilerOnRenderCallback;
2014
+ /**
2015
+ * Test-only virtual-keyboard raise spy (v0.10 plan §6.4 / RC-G2t): called synchronously by
2016
+ * the single `raiseVirtualKeyboard` funnel, so spy count ≡ raise executions — a React-batched
2017
+ * raise-then-lower mutates no DOM (`inputmode` observer-blind) yet still counts. Never
2018
+ * passed in production (zero calls when unset — the `__onCellRender` conduct).
2019
+ * テスト専用の仮想キーボード招待スパイ (v0.10 計画 §6.4 / RC-G2t)。単一漏斗
2020
+ * `raiseVirtualKeyboard` が同期で呼ぶため、計数 ≡ raise 実行 — React バッチの
2021
+ * raise-then-lower は DOM 無変異 (`inputmode` の観測は盲目) でも計数には映る。production
2022
+ * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
2023
+ */
2024
+ __onVirtualKeyboardRaise?: () => void;
1868
2025
  };
1869
2026
 
2027
+ export { TapScrollCircleRenderProps }
2028
+
1870
2029
  /** Case-sensitive needle test on the raw text. / 素の text に対する大文字小文字区別の needle 判定。 */
1871
2030
  export declare type TextCondition = {
1872
2031
  type: "text";