@aiquants/spreadsheet 0.11.0 → 0.13.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
@@ -4,6 +4,8 @@ import { ReactNode } from 'react';
4
4
  import { RefAttributes } from 'react';
5
5
  import { ScrollBarTapCircleOptions } from '@aiquants/virtualscroll';
6
6
  import { TapScrollCircleRenderProps } from '@aiquants/virtualscroll';
7
+ import { VirtualScrollLabels } from '@aiquants/virtualscroll';
8
+ import { VirtualScrollLocale } from '@aiquants/virtualscroll';
7
9
 
8
10
  /** Border colour when `CellBorder.color` is absent (a stated default, not a fallback). / 罫線色の宣言済み既定 (fallback ではなく仕様上の既定)。 */
9
11
  export declare const BORDER_DEFAULT_COLOR = "#000000";
@@ -481,17 +483,6 @@ export declare const DEFAULT_CUSTOM_COLORS: readonly string[];
481
483
  /** Default band palette (plan §1.9) — the same values the `.aqsp-root` CSS variables fall back to. / 既定の帯パレット (計画 §1.9) — `.aqsp-root` の CSS 変数既定と同値。 */
482
484
  export declare const DEFAULT_HIGHLIGHT_COLORS: HighlightColors;
483
485
 
484
- /**
485
- * English defaults for every key. `sinkAriaLabel` / `rootAriaLabel` are byte-identical to the
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";
488
- * `commentCount` and `listMore` pluralise ("1 comment" / "n comments", "1 more value" / "n more values"). Frozen.
489
- * 全キーの英語既定。`sinkAriaLabel` / `rootAriaLabel` は v0.7 の prop 既定と byte 同一 (畳込みは
490
- * DOM 恒等)、`noteEscapeHint` = "Escape saves and closes" とその v0.10 ビューア対応
491
- * `noteViewerHint` = "Escape closes without saving"、`commentCount` / `listMore` は単複を区別。凍結済み。
492
- */
493
- export declare const DEFAULT_LABELS: SpreadsheetLabels;
494
-
495
486
  /**
496
487
  * Default chords per command, derived from the `command === K` rows of BUILTIN_ROWS in table
497
488
  * order (`[]` = unbound by default: hideColumns and every extension command). Validates under
@@ -1043,11 +1034,22 @@ export declare type ReadOnlyRejection = {
1043
1034
  readonly cellCount: number;
1044
1035
  };
1045
1036
 
1046
- /** Public custom cell renderer context (ADR-8). / 公開セルレンダラーの ctx (ADR-8)。 */
1037
+ /**
1038
+ * Public custom cell renderer context (ADR-8). `text` is the RAW canonical `getCellText`
1039
+ * string; `displayText` (v0.12) is the value-format display string — the exact string the
1040
+ * default rendering, the AT announcement, the HTML clipboard and autofit all share (equals
1041
+ * `text` when the format capability is absent). A custom cell that should look like the
1042
+ * default renders `displayText`.
1043
+ * 公開セルレンダラーの ctx (ADR-8)。`text` は素の正準 `getCellText` 文字列。`displayText`
1044
+ * (v0.12) は値書式の表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit が共有
1045
+ * する同一文字列 (書式能力なしは `text` と同値)。既定と同じ見た目にしたいカスタムセルは
1046
+ * `displayText` を描く。
1047
+ */
1047
1048
  export declare type RenderCellContext = {
1048
1049
  row: number;
1049
1050
  col: number;
1050
1051
  text: string;
1052
+ displayText: string;
1051
1053
  };
1052
1054
 
1053
1055
  /**
@@ -1056,9 +1058,44 @@ export declare type RenderCellContext = {
1056
1058
  * returned as-is and ignores `n`.
1057
1059
  * 唯一の読み出し点: ラベル 1 件を表示文字列へ解決。関数値は n で呼ぶ (n 省略は呼び手バグとして
1058
1060
  * RangeError — 黙って 0 にしない)、文字列値はそのまま (n は無視)。
1061
+ *
1062
+ * @param labels - The resolved label bag / 解決済みラベル集合
1063
+ * @param key - The label key to read / 読み出すラベルキー
1064
+ * @param n - The count for a count-aware (function-valued) label / 件数キー (関数値) に渡す件数
1065
+ * @returns The display string / 表示文字列
1066
+ * @throws {RangeError} When the label is a function and `n` is omitted / 関数値で n を省略した場合
1059
1067
  */
1060
1068
  export declare const resolveLabel: (labels: SpreadsheetLabels, key: keyof SpreadsheetLabels, n?: number) => string;
1061
1069
 
1070
+ /**
1071
+ * The single fold point of the `locale` + `labels` props. The locale is resolved by
1072
+ * `resolveVirtualScrollLocale` (undefined ⇒ "en"). `undefined` overrides return
1073
+ * SPREADSHEET_LABEL_CATALOGS[locale] by identity. Otherwise: the overrides must be a plain object
1074
+ * (prototype `Object.prototype` or `null`) whose own keys all belong to LABEL_KEYS, and only its
1075
+ * own properties are read; the engine subset is resolved by `resolveVirtualScrollLabels` (the
1076
+ * engine's own validation); an own key takes its override when it is not `undefined`
1077
+ * (destructuring-default semantics of the folded v0.7 props) and the catalog value otherwise; the
1078
+ * result is validated by assertLabels and frozen. Inputs are never mutated.
1079
+ * `locale` + `labels` prop の唯一の畳込み点。ロケールは `resolveVirtualScrollLocale` で解決
1080
+ * (undefined は "en")。override 未指定は SPREADSHEET_LABEL_CATALOGS[locale] を identity で返却。
1081
+ * それ以外は、override は自身のキーがすべて LABEL_KEYS に属する素の object (プロトタイプが
1082
+ * `Object.prototype` か `null`) で、読むのは自身のプロパティのみ。エンジン部分は
1083
+ * `resolveVirtualScrollLabels` (エンジン自身の検証) で解決、固有キーは undefined でない override を採用し
1084
+ * それ以外はカタログ値 (畳み込んだ v0.7 prop の分割代入既定の意味論)、結果は assertLabels で検証し凍結。
1085
+ * 入力は変更しない。
1086
+ *
1087
+ * @param locale - UI chrome locale, or `undefined` for the default "en" / UI クロームロケール (`undefined` で既定の "en")
1088
+ * @param overrides - Per-key overrides, or `undefined` for none / キー単位の上書き (`undefined` で上書きなし)
1089
+ * @returns The resolved, frozen label bag / 解決済みの凍結ラベル集合
1090
+ * @throws {RangeError} When the locale is unsupported, the overrides are `null` / not an object,
1091
+ * the overrides are not a plain object (an array, a class instance, an object inheriting from
1092
+ * another object), an own key is not a label key (including the removed validationRejected /
1093
+ * indicator* keys), or a value violates its key's rule / ロケールが非対応、override が `null` /
1094
+ * 非 object、override が素の object でない (配列・クラスインスタンス・他 object 継承)、自身のキーが
1095
+ * ラベルキー外 (削除済みの validationRejected / indicator* を含む)、または値がキーの規則に違反した場合
1096
+ */
1097
+ export declare const resolveLabels: (locale: SpreadsheetLocale | undefined, overrides: SpreadsheetLabelOverrides | undefined) => SpreadsheetLabels;
1098
+
1062
1099
  /** One colour-scale point; `value` omitted = the range extremum from `getRangeExtrema` (min / max) or the arithmetic midpoint (mid). / 色スケールの 1 点。value 省略 = getRangeExtrema のレンジ極値 (min / max) か算術中点 (mid)。 */
1063
1100
  export declare type ScalePoint = {
1064
1101
  color: string;
@@ -1156,6 +1193,16 @@ export declare type ShortcutOverrides = {
1156
1193
  */
1157
1194
  export declare const Spreadsheet: ForwardRefExoticComponent<SpreadsheetProps & SpreadsheetTestProps & RefAttributes<SpreadsheetHandle>>;
1158
1195
 
1196
+ /**
1197
+ * Frozen full catalogs per locale (outer record and every entry frozen): each entry is the engine
1198
+ * catalog `VIRTUAL_SCROLL_LABEL_CATALOGS[locale]` (reused by value — single source of truth for
1199
+ * the 7 chrome strings) overlaid by the own-key catalog of the same locale.
1200
+ * ロケール別の凍結済み完全カタログ (外側のレコードと各エントリを凍結): 各エントリはエンジンカタログ
1201
+ * `VIRTUAL_SCROLL_LABEL_CATALOGS[locale]` (値を再利用 — 7 クローム文言の単一の真実源) に同ロケールの
1202
+ * 固有キーカタログを重ねたもの。
1203
+ */
1204
+ export declare const SPREADSHEET_LABEL_CATALOGS: Readonly<Record<SpreadsheetLocale, SpreadsheetLabels>>;
1205
+
1159
1206
  /**
1160
1207
  * Reserved chords for EVERY command: the exact chords of `rebindable: false` rows consulted in
1161
1208
  * the idle column (`"idle" | "both"` — every command is consulted there). Editing-only rows
@@ -1271,10 +1318,12 @@ export declare type SpreadsheetDataAdapter = {
1271
1318
  * string only — editing keeps the raw getCellText (Excel semantics) and copy/TSV carry the raw
1272
1319
  * value too (a DELIBERATE deviation from Excel, which copies the display — raw preserves the
1273
1320
  * 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
1321
+ * announcements receive both the raw text and the display string. A `renderCell` (prop)
1322
+ * cell that returns custom output shows that output instead of the built-in VALUE format
1323
+ * (raw `text` and the formatted `displayText` both flow to the custom renderer); a cell whose
1324
+ * renderCell returns `undefined` falls back to the formatted default (v0.12 per-cell opt-out),
1325
+ * and the resolved ALIGNMENT and paint are cell properties that apply under renderCell
1326
+ * regardless. Every format is fail-soft: a non-numeric value in a numeric format, an
1278
1327
  * invalid date, an out-of-range Intl option or an unparseable colour renders / paints
1279
1328
  * nothing for that key. Return a shared/interned CellFormat per column (or per cell object)
1280
1329
  * to avoid per-cell allocation and to keep the paint intern stable; because return values
@@ -1288,9 +1337,10 @@ export declare type SpreadsheetDataAdapter = {
1288
1337
  * **塗り書式** (この base ⊕ 条件付き書式)。値書式は表示文字列にのみ適用し、編集は素の
1289
1338
  * getCellText (Excel 意味論)、コピー / TSV も素の値を運ぶ (Excel は表示を写すため**意図的な
1290
1339
  * 逸脱** — 素値は数値の往復を保つ)。autofit は**整形後の表示**を計測し、読み上げには素の
1291
- * text と表示文字列の両方を渡す。`renderCell` (prop) は組み込み「値書式」に優先する (素の
1292
- * text がカスタムレンダラーへ) が、解決済み「揃え」と塗りはセル固有属性として renderCell 下
1293
- * でも効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1340
+ * text と表示文字列の両方を渡す。`renderCell` (prop) がカスタム出力を返したセルは組み込み
1341
+ * 「値書式」の代わりにその出力を描く (素の text と整形後 displayText の両方がカスタム
1342
+ * レンダラーへ)。undefined を返したセルは整形済みの既定描画へ降りる (v0.12 のセル単位
1343
+ * オプトアウト)。解決済み「揃え」と塗りはセル固有属性として renderCell 下でも常に効く。全書式は fail-soft — 数値書式の非数値・無効な日付・範囲外 Intl オプション・解釈
1294
1344
  * 不能な色はそのキーだけ何も描かない。列毎 (またはセル object 毎) に共有 CellFormat を返すと
1295
1345
  * セル毎の確保を避け塗りの intern も安定する。戻り値は (getCellText 同様) 再スライス時のみ
1296
1346
  * 再読込されるため、書式変更の反映は dataVersion 増分 (またはアダプタ差替) で行う。
@@ -1403,6 +1453,31 @@ export declare type SpreadsheetDataAdapter = {
1403
1453
  * (getCellText と同格、描画パスでも呼ばれるため)。未宣言 = 全セル編集可 = 従来挙動とバイト同一。
1404
1454
  */
1405
1455
  isCellReadOnly?: (row: number, col: number) => boolean;
1456
+ /**
1457
+ * OPTIONAL capability (v0.12): host-owned `data-*` attributes for one cell, merged verbatim
1458
+ * onto the PACKAGE-OWNED cell element (`[data-aqsp-cell]`) so host CSS can target cell
1459
+ * state, `:hover` and theme tokens without wrapper elements inside the cell. The package
1460
+ * never interprets the values. Validated fail-fast at render (RangeError): the return must
1461
+ * be a plain record or `null` (a JS host's `undefined` / array / Map is rejected by name,
1462
+ * never a bare TypeError), every key must be a lowercase `data-*` name
1463
+ * (`data-[a-z0-9-]+`), the package- and engine-emitted cell attributes (`data-aqsp*`,
1464
+ * `data-aqvs*`, `data-row`, `data-col`) are reserved, and every value must be a string
1465
+ * (React would otherwise stringify objects or drop `undefined` silently). Read once per
1466
+ * painted cell per slice (the `getCellText` cost budget — keep it O(1)); publish changes
1467
+ * via `dataVersion`. `null` = no extra attributes for this cell. Absence = the previous
1468
+ * version's cell DOM byte-identically.
1469
+ * 任意能力 (v0.12): セル 1 つへのホスト所有 `data-*` 属性 — パッケージ所有のセル要素
1470
+ * (`[data-aqsp-cell]`) へそのまま載せる継ぎ目。セル内に器 (ラッパー要素) を敷かずにホスト
1471
+ * CSS がセル状態・`:hover`・テーマトークンを掴むための口で、値の解釈はパッケージが
1472
+ * 持たない。render 時 fail-fast 検証 (RangeError): 戻りはプレーンな record か `null`
1473
+ * (JS ホストの `undefined` / 配列 / Map は名指しで拒否 — 生 TypeError にしない)、キーは
1474
+ * 小文字 `data-*` (`data-[a-z0-9-]+`) のみ、パッケージ / エンジン放出のセル属性
1475
+ * (`data-aqsp*` / `data-aqvs*` / `data-row` / `data-col`) は予約、値は string のみ (React の
1476
+ * 暗黙文字列化や `undefined` の無言脱落を許さない)。描画セル毎・スライス毎に 1 読み
1477
+ * (getCellText と同格の予算 — O(1) に保つ)。変更は dataVersion で公開。null = このセルに
1478
+ * 追加属性なし。未宣言 = 従来のセル DOM とバイト同一。
1479
+ */
1480
+ getCellAttributes?: (row: number, col: number) => Readonly<Record<string, string>> | null;
1406
1481
  /**
1407
1482
  * OPTIONAL capability (v0.8): the numeric minimum / maximum over a range, for colorScale
1408
1483
  * rules whose end points omit `value`; null = the range holds no numeric value. Memoised by
@@ -1488,48 +1563,22 @@ export declare type SpreadsheetHandle = {
1488
1563
 
1489
1564
  /**
1490
1565
  * The `labels` prop shape: any subset of SpreadsheetLabels (an omitted or `undefined` key keeps
1491
- * the default). Keys are closed to SpreadsheetLabels.
1492
- * `labels` prop の形: SpreadsheetLabels の任意の部分集合 (省略 / undefined は既定のまま)。キーは
1493
- * SpreadsheetLabels に閉じる。
1566
+ * the catalog value of the chosen locale). Keys are closed to SpreadsheetLabels.
1567
+ * `labels` prop の形: SpreadsheetLabels の任意の部分集合 (省略 / undefined は選択ロケールのカタログ値の
1568
+ * まま)。キーは SpreadsheetLabels に閉じる。
1494
1569
  */
1495
1570
  export declare type SpreadsheetLabelOverrides = {
1496
1571
  readonly [K in keyof SpreadsheetLabels]?: SpreadsheetLabels[K];
1497
1572
  };
1498
1573
 
1499
1574
  /**
1500
- * @fileoverview UI label vocabulary (v0.8 §1.6 / §4.1.17) — the ONE label bag of the package.
1501
- * The v0.7 `sinkAriaLabel` / `rootAriaLabel` props are folded into it (clean cut-over: no alias
1502
- * props remain), joined by the popover / indicator strings of the rich-cell UI. Pure, React-free.
1503
- *
1504
- * Contract (each clause is pinned by labels.spec.ts):
1505
- * - `SpreadsheetLabels` is the closed key set; `DEFAULT_LABELS` supplies an English default for
1506
- * every key. Count-aware keys are typed `string | ((n: number) => string)`.
1507
- * - `resolveLabels(overrides)` is the single fold point: a key takes its override when the
1508
- * override is not `undefined` and the default otherwise (exactly the destructuring-default
1509
- * semantics the two folded props had in v0.7), then `assertLabels` runs on the result.
1510
- * `undefined` overrides resolve to `DEFAULT_LABELS` by identity.
1511
- * - `assertLabels`: `sinkAriaLabel` MUST be a string mentioning "Escape" (WCAG 2.1.2 escape-method
1512
- * advisement, spec 00 §10-4) — otherwise a RangeError, thrown at mount by the root.
1513
- * - `resolveLabel(labels, key, n)` is the single read point: a function-valued label receives `n`
1514
- * (omitting `n` for a function value is a RangeError — never a silent 0), a string is returned
1515
- * as-is (`n` ignored, so a consumer may override a count key with a plain string).
1516
- *
1517
- * UI ラベル語彙 (v0.8 §1.6 / §4.1.17) — パッケージ唯一のラベル集合。v0.7 の `sinkAriaLabel` /
1518
- * `rootAriaLabel` prop を畳み込み (クリーンカットオーバー: 別名 prop は残さない)、リッチセル UI の
1519
- * ポップオーバー / インジケータ文言を加える。純関数・React 非依存。
1520
- * 契約: `SpreadsheetLabels` は閉じたキー集合、`DEFAULT_LABELS` は全キーの英語既定、件数キーは
1521
- * `string | ((n: number) => string)`。`resolveLabels` が唯一の畳込み点 (undefined でない override を
1522
- * 採用、それ以外は既定 — 畳み込んだ 2 prop が v0.7 で持っていた分割代入既定と同じ意味論。
1523
- * override 未指定は `DEFAULT_LABELS` を identity で返却) で、続けて `assertLabels`
1524
- * (`sinkAriaLabel` は "Escape" を含む文字列であること — spec 00 §10-4、違反はマウント時 RangeError)。
1525
- * `resolveLabel` が唯一の読み出し点 (関数値は n 必須 — 省略は RangeError、文字列はそのまま)。
1526
- */
1527
- /**
1528
- * The closed label vocabulary. Every key has a default in DEFAULT_LABELS; consumers override any
1529
- * subset through the `labels` prop (SpreadsheetLabelOverrides).
1530
- * 閉じたラベル語彙。全キーが DEFAULT_LABELS に既定を持ち、消費者は `labels` prop で任意の部分集合を上書き。
1531
- */
1532
- export declare type SpreadsheetLabels = {
1575
+ * The closed label vocabulary: the 7 engine chrome keys of `@aiquants/virtualscroll` plus the 21
1576
+ * own keys of the spreadsheet. Every key has a value in each SPREADSHEET_LABEL_CATALOGS entry;
1577
+ * consumers override any subset through the `labels` prop (SpreadsheetLabelOverrides).
1578
+ * 閉じたラベル語彙: `@aiquants/virtualscroll` のエンジンクローム 7 キーとスプレッドシート固有の 21 キー。
1579
+ * 全キーが SPREADSHEET_LABEL_CATALOGS の各ロケールに値を持ち、消費者は `labels` prop で任意の部分集合を上書き。
1580
+ */
1581
+ export declare type SpreadsheetLabels = VirtualScrollLabels & {
1533
1582
  /** Accessible name of the sink (grid input receptor); MUST mention "Escape" (spec 00 §10-4). / シンクのアクセシブルネーム ("Escape" 必須)。 */
1534
1583
  sinkAriaLabel: string;
1535
1584
  /** Accessible name of the root role="group" landing point. / root 着地点のアクセシブルネーム。 */
@@ -1570,18 +1619,21 @@ export declare type SpreadsheetLabels = {
1570
1619
  listMore: string | ((n: number) => string);
1571
1620
  /** Message popover heading. / メッセージポップオーバーの見出し。 */
1572
1621
  messageTitle: string;
1573
- /** Message shown when a strict validation rule rejects the typed value. / 厳格検証で拒否されたときの文言。 */
1574
- validationRejected: string;
1575
1622
  /** Close button of every popover. / ポップオーバー共通の閉じるボタン。 */
1576
1623
  popoverClose: string;
1577
- /** Accessible label of the note indicator on a cell. / ノートインジケータのラベル。 */
1578
- indicatorNote: string;
1579
- /** Accessible label of the comment indicator on a cell. / コメントインジケータのラベル。 */
1580
- indicatorComment: string;
1581
- /** Accessible label of the invalid-value indicator on a cell. / 無効値インジケータのラベル。 */
1582
- indicatorInvalid: string;
1583
1624
  };
1584
1625
 
1626
+ /**
1627
+ * The UI chrome language of the spreadsheet ("en" | "ja") — the engine's locale set, so the grid
1628
+ * body and the embedded scroll chrome always speak one language. A different axis from
1629
+ * `formats.locale`, which is the BCP-47 locale of value formatting (numbers / dates); a BCP-47 tag
1630
+ * such as "ja-JP" is NOT a SpreadsheetLocale.
1631
+ * スプレッドシートの UI クローム言語 ("en" | "ja") — エンジンのロケール集合そのもので、グリッド本体と
1632
+ * 埋込みスクロールクロームが常に同一言語。値書式 (数値 / 日付) の BCP-47 ロケールである
1633
+ * `formats.locale` とは別軸 ("ja-JP" のような BCP-47 タグは SpreadsheetLocale ではない)。
1634
+ */
1635
+ export declare type SpreadsheetLocale = VirtualScrollLocale;
1636
+
1585
1637
  /**
1586
1638
  * Bulk-operation kind for the ADR-12 rejection channel (public vocabulary). Serialize-only
1587
1639
  * gestures ("copy" / "cut"), grid geometry ("resize") and the WRITE gestures ("delete" /
@@ -1681,16 +1733,27 @@ export declare type SpreadsheetProps = {
1681
1733
  /**
1682
1734
  * Row-axis overscan pass-through (the VirtualGrid `overscanRows` knob; LIVE prop): rows
1683
1735
  * 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).
1736
+ * engine's one-frame rendering-window lag during fast scrolling (the blank-band remedy).
1737
+ * Overscan counts ROWS — hidden 0-height rows consume slots too — so the px slack per edge
1738
+ * is overscan × row height only where rows are uniform and visible. Undefined ⇒ the engine
1739
+ * default (3). The engine does not validate overscan (a negative value silently shrinks the
1740
+ * rendering window), so THIS surface owns the fail-fast: a non-integer or negative value
1741
+ * throws a RangeError at render. Cost multiplies with the column axis, and the engine
1742
+ * TRUNCATES rather than bounds: a window beyond its per-axis row budget or its total cell
1743
+ * cap keeps the LEADING side and drops the trailing side — the row-budget case has no
1744
+ * callback (the engine only logs a warning), the cell-cap case (columns dropped) reports
1745
+ * through `onRenderTruncated`. Values of
1746
+ * hundreds of rows per side approach that budget on tall viewports; keep overscan to the
1747
+ * slack you need.
1689
1748
  * 行軸 overscan の素通し (VirtualGrid `overscanRows`。ライブ prop): 縦 viewport 端の外側へ
1690
- * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策 —
1691
- * 余裕 px は片端あたり overscan × 行高)。undefined はエンジン既定 (3)。エンジンは不正値を
1692
- * 無言クランプするため fail-fast は本層所有 — 非整数・負値は render 時 RangeError。費用は
1693
- * 列軸との積で増幅 (エンジンのセル上限で有界)。
1749
+ * 描画する行数。高速スクロール時の描画窓 1 フレーム遅れを吸収する唯一の余裕 (白帯対策)。
1750
+ * overscan は**行数**で数える (非表示の 0px 行も枠を消費) ため、片端の余裕 px が overscan ×
1751
+ * 行高になるのは行が一様に可視のときだけ。undefined はエンジン既定 (3)。エンジンは overscan を
1752
+ * 検証しない (負値は描画窓を無言で縮める) ため fail-fast は本層所有 — 非整数・負値は render 時
1753
+ * RangeError。費用は列軸との積で増幅し、エンジンは有界化でなく**打切り**で応じる: 軸毎の行予算
1754
+ * や総セル上限を超えた窓は先頭側を残し末尾側を落とす — 行予算超過はコールバック無し (エンジンは
1755
+ * warn ログのみ)、セル上限超過 (列の脱落) は `onRenderTruncated` で通知。片側数百行の値は高い viewport で予算に迫るため、必要な
1756
+ * 余裕にとどめる。
1694
1757
  */
1695
1758
  overscanRows?: number;
1696
1759
  /**
@@ -1707,18 +1770,55 @@ export declare type SpreadsheetProps = {
1707
1770
  * translates only its row wrapper, so this layer does NOT follow the scroll offset —
1708
1771
  * periodic row ruling placed here slides against the real rows while scrolling. Suited to
1709
1772
  * a static texture that reads as "content still arriving" in the overscan-exhausted band,
1710
- * not to row-aligned gridlines.
1773
+ * not to row-aligned gridlines. The layer spans the full width of the scroll rows — the
1774
+ * frozen-COLUMN region included (frozen columns live inside the scroll rows) — but not the
1775
+ * frozen row bands. Identity-stable contract (same as `renderCell`): an inline element here
1776
+ * pierces the GridBody memo boundary on every host re-render (the engine's render bodies
1777
+ * re-run; cells stay memoized) — hoist the node or `useMemo` it.
1711
1778
  * スクロール帯行の背後・エンジンコンテンツ要素内に描画する背景レイヤー (VirtualGrid
1712
1779
  * `background` の素通し。ライブ prop)。viewport 固定: エンジンが translate するのは行
1713
1780
  * ラッパーだけで、この層はスクロール量に追従しない — 周期的な行罫線を置くとスクロール中に
1714
1781
  * 実際の行へ対して滑る。overscan が尽きた帯で「まだ到着中」と読める静的テクスチャ向きで、
1715
- * 行整合の罫線には不向き。
1782
+ * 行整合の罫線には不向き。層はスクロール行の全幅 — 凍結**列**域を含む (凍結列はスクロール行の
1783
+ * 内側に居る) — に広がり、凍結行帯には広がらない。identity 安定契約 (`renderCell` と同じ):
1784
+ * インライン要素はホスト再レンダー毎に GridBody の memo 境界を貫通する (エンジンの render 本体が
1785
+ * 再実行、セルは memo 維持) — ノードは hoist するか `useMemo` で保つ。
1716
1786
  */
1717
1787
  background?: ReactNode;
1788
+ /**
1789
+ * Rendering-truncation signal pass-through (the VirtualGrid `onRenderTruncated` callback):
1790
+ * fires when the engine drops trailing columns to stay under its total cell cap
1791
+ * (`MAX_RENDERED_CELLS`) — the cells actually rendered and the columns dropped. The engine's
1792
+ * doctrine is that truncation is never silent; an oversized `overscanCols` × row span is the
1793
+ * typical cause. Undefined ⇒ no callback (engine default).
1794
+ * 描画打切り通知の素通し (VirtualGrid `onRenderTruncated`): エンジンが総セル上限
1795
+ * (`MAX_RENDERED_CELLS`) を守るため末尾列を落としたときに、実描画セル数と脱落列数で発火する。
1796
+ * 「打切りは無言にしない」がエンジン教義で、過大な `overscanCols` × 行スパンが典型原因。
1797
+ * undefined = 通知なし (エンジン既定)。
1798
+ */
1799
+ onRenderTruncated?: (info: {
1800
+ renderedCells: number;
1801
+ droppedCols: number;
1802
+ }) => void;
1718
1803
  /**
1719
1804
  * Identity-stable contract (same as adapter): an inline arrow here defeats the CellView memo
1720
1805
  * and turns every host re-render into a full visible re-slice (~800 cells at 16k columns).
1721
- * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。
1806
+ * Per-cell opt-out (v0.12): returning `undefined` from one cell lands that cell on the
1807
+ * package default rendering (value-format engine included) — "custom where needed, default
1808
+ * elsewhere" without wrapper elements. ONLY `undefined` opts out — `null`, `false` (the
1809
+ * `cond && <X/>` idiom) and every other ReactNode are custom output, i.e. an empty custom
1810
+ * cell. `ctx.text` is the RAW canonical string; `ctx.displayText` (v0.12) is the value-format
1811
+ * display — the exact string the default rendering, the AT announcement, the HTML clipboard
1812
+ * and autofit share, so a custom cell that renders it can never drift from what gets copied.
1813
+ * Autofit stays a whole-grid no-op while `renderCell` is set (custom DOM width is unknowable).
1814
+ * identity 安定契約 — インライン関数は memo を無効化し毎レンダー全再スライスになる。セル単位
1815
+ * オプトアウト (v0.12): `undefined` を返したセルはパッケージ既定描画 (値書式エンジン込み) へ
1816
+ * 降りる — 「要る列だけカスタム、残りは既定」を器なしで構成できる。オプトアウトは
1817
+ * `undefined` **だけ** — `null` / `false` (`cond && <X/>` 慣用) / 他の ReactNode はカスタム
1818
+ * 出力 (= 空のカスタムセル)。`ctx.text` は素の正準文字列、`ctx.displayText` (v0.12) は値書式の
1819
+ * 表示文字列 — 既定描画・AT 読み上げ・HTML クリップボード・autofit と同一なので、これを描く
1820
+ * カスタムセルはコピー結果と食い違わない。autofit は `renderCell` 指定中はグリッド全体
1821
+ * no-op のまま (カスタム DOM の幅は測れない)。
1722
1822
  */
1723
1823
  renderCell?: (ctx: RenderCellContext) => ReactNode;
1724
1824
  /**
@@ -1726,11 +1826,16 @@ export declare type SpreadsheetProps = {
1726
1826
  * paste replace, Ctrl+A, ...). Never during a drag (state frozen — one fire at pointerup),
1727
1827
  * with ONE documented in-drag firing point: the header subtract reservation converts to a
1728
1828
  * 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).
1829
+ * count matches v0.1 — conversion 1 + up 1). Never for the initial A1 mount. ONE host-driven
1830
+ * fire point outside gestures (ADR-33): a same-adapter rowCount / colCount shrink that moved
1831
+ * the selection fires once from a layout effect of that commit — not a user gesture.
1832
+ * Independent of the live region's 200ms debounce (firing point: the §6.9-1 setSelection
1833
+ * wrapper).
1731
1834
  * 確定 SelectionState が変わるたびに発火。ドラッグ中と初期マウントでは発火しない。明文の
1732
1835
  * ドラッグ中発火点が 1 つ: ヘッダー減算予約の実 press 変換 (初動 move) は遅延 press 置換を
1733
- * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。
1836
+ * ドラッグ中に発火する (発火総数は v0.1 と同一 — 変換 1 + up 1)。ジェスチャ外のホスト起点発火点が
1837
+ * 1 つ (ADR-33): 同一 adapter の rowCount / colCount 縮小で選択が動いたとき、その commit の
1838
+ * layout effect から 1 回発火する (ユーザー操作ではない)。
1734
1839
  */
1735
1840
  onSelectionChange?: (selection: SelectionState) => void;
1736
1841
  /** Consumer context menu (§6.4.3-4 / §6.6.1 Shift+F10); keyboard origin carries the active cell viewport rect. / consumer コンテキストメニュー。 */
@@ -1834,9 +1939,11 @@ export declare type SpreadsheetProps = {
1834
1939
  enableResizeUI?: boolean;
1835
1940
  /**
1836
1941
  * 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
1942
+ * is the RAW canonical getCellText; `displayText` is the value-format display string (the
1838
1943
  * 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
1944
+ * hear "87.0%" for a cell whose raw value is "0.87". It is the same string a custom
1945
+ * `renderCell` cell receives as `ctx.displayText` (v0.12) — what a sighted user sees unless
1946
+ * the host deliberately renders something else. `readOnly` (v0.10) is
1840
1947
  * declaration-gated three-valued: the key is ABSENT when the adapter does not declare
1841
1948
  * `isCellReadOnly` (payload byte-identical to v0.9), `false` = declared editable, `true` =
1842
1949
  * declared read-only — the navigation-time read-only channel (DOM focus stays on the sink,
@@ -1874,14 +1981,30 @@ export declare type SpreadsheetProps = {
1874
1981
  command: SpreadsheetCommand;
1875
1982
  state: boolean | null;
1876
1983
  }) => string;
1984
+ /**
1985
+ * UI chrome language ("en" | "ja"; default "en"): selects the label catalog, the built-in
1986
+ * data-validation messages, and is forwarded to the grid scrollbars (arrow labels,
1987
+ * scroll-to-edge pills, "No items"). An unsupported value throws a RangeError during render —
1988
+ * there is no language negotiation: hosts map `navigator.language` themselves. Unrelated to
1989
+ * `formats.locale`, which is the BCP-47 value-formatting locale ("ja-JP" is NOT a valid value
1990
+ * here).
1991
+ * UI クローム言語 ("en" | "ja"、既定 "en"): ラベルカタログと組み込みデータ検証メッセージを選び、
1992
+ * グリッドのスクロールバー (矢印ラベル・端スクロールピル・"No items") へ素通し。非対応値は render 中
1993
+ * RangeError — 言語ネゴシエーションなし (`navigator.language` の写像はホスト側)。値書式の BCP-47
1994
+ * ロケールである `formats.locale` とは無関係 ("ja-JP" はここでは不正値)。
1995
+ */
1996
+ locale?: SpreadsheetLocale;
1877
1997
  /**
1878
1998
  * UI label vocabulary (v0.8 §1.6) — folds the former `sinkAriaLabel` / `rootAriaLabel` props
1879
- * (clean cut-over). An omitted or explicitly `undefined` key keeps the English default. The
1880
- * resolved `sinkAriaLabel` MUST mention "Escape" (WCAG 2.1.2 escape advisement, §10-4) — a
1881
- * RangeError is thrown during render otherwise.
1999
+ * (clean cut-over). 28 keys = the 7 engine chrome keys (scrollUp / scrollDown / scrollLeft /
2000
+ * scrollRight / scrollToTop / scrollToBottom / noItems) + 21 own keys. An omitted prop or an
2001
+ * explicitly `undefined` key keeps the value of the `locale` catalog. An unknown key or an
2002
+ * empty / blank value throws a RangeError during render, and the resolved `sinkAriaLabel` MUST
2003
+ * mention "Escape" (WCAG 2.1.2 escape advisement, §10-4).
1882
2004
  * UI ラベル語彙 (v0.8 §1.6) — 旧 sinkAriaLabel / rootAriaLabel prop を畳込み (クリーンカットオーバー)。
1883
- * 省略 / 明示 undefined は英語既定。解決後の sinkAriaLabel は "Escape" を含むこと (違反は render 中
1884
- * RangeError — §10-4)。
2005
+ * 28 キー = エンジンクローム 7 キー (scrollUp / scrollDown / scrollLeft / scrollRight / scrollToTop /
2006
+ * scrollToBottom / noItems) + 固有 21 キー。prop 省略 / 明示 undefined のキーは `locale` のカタログ値。
2007
+ * 未知キー・空 / 空白値は render 中 RangeError、解決後の sinkAriaLabel は "Escape" を含むこと (§10-4)。
1885
2008
  */
1886
2009
  labels?: SpreadsheetLabelOverrides;
1887
2010
  /**
@@ -1948,7 +2071,7 @@ export declare type SpreadsheetProps = {
1948
2071
  onClipChange?: (clip: ClipInfo | null) => void;
1949
2072
  /** Hyperlink navigation seam (Alt+Enter, the link popover's Open button, and Ctrl / Meta+click on a link cell — spec 08 §11 D-53) — undeclared ⇒ no navigation, no Open button, no pointer gesture. / ハイパーリンク遷移シーム (Alt+Enter / Open ボタン / リンクセルへの Ctrl / Meta+クリック — 分冊 08 §11 D-53)。未宣言 = 遷移なし・Open ボタンなし・ポインタジェスチャなし。 */
1950
2073
  onHyperlinkOpen?: (url: string, cell: CellCoord) => void;
1951
- /** Strict validation rejection notice (v0.8 §1.9) — the commit never reaches the adapter; the message popover shows the rejection. / strict 検証拒否の通知 (commit はアダプタへ届かず、message ポップオーバーが拒否を示す)。 */
2074
+ /** Strict validation rejection notice (v0.8 §1.9) — the commit never reaches the adapter; the message popover shows the rejection. `message` is `rule.errorMessage` when declared, otherwise the built-in message in the active `locale`. / strict 検証拒否の通知 (commit はアダプタへ届かず、message ポップオーバーが拒否を示す)。`message` は `rule.errorMessage` 宣言時はそれ、未宣言なら現在の `locale` の組み込みメッセージ。 */
1952
2075
  onValidationRejected?: (ctx: {
1953
2076
  cell: CellCoord;
1954
2077
  rule: DataValidationRule;
@@ -2022,6 +2145,15 @@ declare type SpreadsheetTestProps = {
2022
2145
  * では渡さない (未指定 = 呼出しゼロ — `__onCellRender` と同じ品行)。
2023
2146
  */
2024
2147
  __onVirtualKeyboardRaise?: () => void;
2148
+ /**
2149
+ * Test-only rendered-cell cap forwarded to the engine's `__maxRenderedCells` seam so the
2150
+ * `onRenderTruncated` pass-through can be pinned without materializing 32,768 cells. Never
2151
+ * passed in production (unset = the engine's MAX_RENDERED_CELLS — the `__onCellRender` conduct).
2152
+ * テスト専用の描画セル上限 (エンジンの `__maxRenderedCells` シームへ素通し) — `onRenderTruncated`
2153
+ * 素通しを 32,768 セルの実体化なしでピンするため。production では渡さない (未指定 = エンジンの
2154
+ * MAX_RENDERED_CELLS — `__onCellRender` と同じ品行)。
2155
+ */
2156
+ __maxRenderedCells?: number;
2025
2157
  };
2026
2158
 
2027
2159
  export { TapScrollCircleRenderProps }
@@ -2060,65 +2192,30 @@ export declare type TextValidationRule = {
2060
2192
  export declare const toR1C1: (formula: string, origin: CellCoord) => string;
2061
2193
 
2062
2194
  /**
2063
- * Validates committed text against a rule. Blank always passes; `custom` is evaluated only when
2064
- * the caller passes `evaluate` (commit time — paint omits it); an incomplete rule (unparseable
2065
- * bound, missing `b` / `value`) is inert; a rule outside the vocabulary throws RangeError.
2066
- * Message = `rule.errorMessage` when set, else a built-in English summary of the rule.
2067
- * 確定テキストの規則検証。空文字は常に合格、custom は呼び手が evaluate を渡すとき (確定時 — 描画は
2068
- * 渡さない) だけ評価、不完全な規則 (解釈不能な境界・b / value 欠落) は不活性、語彙外の規則は
2069
- * RangeError。メッセージは errorMessage があればそれ、無ければ組込みの英語要約。
2070
- */
2071
- export declare const validateCellText: (rule: DataValidationRule, text: string, evaluate?: ValidationEvaluate) => ValidationVerdict;
2072
-
2073
- /**
2074
- * @fileoverview Data-validation rule vocabulary and the pure verdict engine (v0.8 — the
2075
- * getCellValidation capability, ADR-13). The consumer declares a per-cell DataValidationRule
2076
- * via the optional adapter capability getCellValidation(row, col); the editor asks
2077
- * validateCellText at COMMIT (passing the adapter's formula evaluator for `custom` rules) and
2078
- * the grid asks isVisiblyInvalid at PAINT (never evaluating a formula) to draw the invalid
2079
- * indicator. React-free and total.
2080
- *
2081
- * Engine contract (each clause is load-bearing and mutation-gated — spec 01 §8.3):
2082
- * - BLANK IS ALWAYS VALID: the empty string satisfies every rule (Excel "ignore blank"), so a
2083
- * validated cell can always be cleared; `custom` is not even evaluated for a blank.
2084
- * - EXACT decimal comparison for `number` rules: the cell text and both bounds are parsed with
2085
- * the SAME strict-decimal grammar as cellFormat.ts (`[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d{1,4})?`,
2086
- * trimmed, no hex / grouping / ±Infinity) and compared as normalised sign / significant-digit /
2087
- * point-position triples — never through a binary double — so "9007199254740993" is greater
2088
- * than "9007199254740992" and "0.30000000000000004" is not equal to "0.3".
2089
- * - TIMEZONE-FREE dates for `date` rules: the pure-calendar grammar of cellFormat.ts
2090
- * ("YYYY-MM-DD[ T HH:mm[:ss]]" or "/" separated, leap-aware ranges, no Date object), compared
2091
- * as (year, month, day, hour, minute, second) tuples; `between` / `notBetween` are inclusive.
2092
- * - INERT INCOMPLETE RULES: a bound that does not parse (`a` / `b` for number / date, a
2093
- * non-finite `a` / `b` for textLength, a missing `b` for between / notBetween, a missing `value`
2094
- * for the needle text ops) makes the rule accept everything — a half-written rule never locks a
2095
- * cell. Bounds are never swapped: `between 10 and 5` accepts nothing but blank.
2096
- * - FAIL-FAST on a rule OUTSIDE the vocabulary: an unknown `type` or `op` is a consumer bug and
2097
- * throws RangeError regardless of the text (fail-soft would silently disable validation).
2098
- * - INTERNED list Sets per rule object (WeakMap identity), so the paint-time `list` check is O(1)
2099
- * even for a 10k-item list; a fresh rule object interns a fresh Set.
2100
- * - MESSAGE resolution: `errorMessage` when the consumer set it (an empty string is honoured as
2101
- * is), else a built-in English summary of the rule.
2102
- * - `custom` needs the caller's `evaluate`; without it the rule is not evaluated (verdict ok), and
2103
- * truth = `true` or a finite non-zero number (the conditionalFormat customFormula convention).
2104
- * - Matching is exact (case-sensitive, untrimmed) for `list` / `text` / `checkbox`; textLength
2105
- * counts Unicode code points. `isEmail` is the WHATWG valid-e-mail grammar with a mandatory
2106
- * dotted domain; `isUrl` is a WHATWG-parsable absolute http(s) URL.
2195
+ * Validates committed text against a rule. The locale is checked FIRST (before the rule and the
2196
+ * text), so an unsupported locale fails fast even for a passing text — this pure function has no
2197
+ * hidden default locale. Blank always passes; `custom` is evaluated only when the caller passes
2198
+ * `evaluate` (commit time — paint omits it); an incomplete rule (unparseable bound, missing `b` /
2199
+ * `value`) is inert; a rule outside the vocabulary throws RangeError. Message = `rule.errorMessage`
2200
+ * when set (the empty string included), else the built-in summary in the given locale.
2201
+ * 確定テキストの規則検証。ロケールを最初に (規則と text より前に) 検査するため、非対応ロケールは
2202
+ * 合格する text でも fail-fast (純関数に隠れた既定ロケールは無い)。空文字は常に合格、custom は呼び手が
2203
+ * evaluate を渡すとき (確定時 — 描画は渡さない) だけ評価、不完全な規則 (解釈不能な境界・b / value 欠落) は
2204
+ * 不活性、語彙外の規則は RangeError。メッセージは errorMessage があればそれ (空文字も含む)、無ければ
2205
+ * 指定ロケールの組込み要約。
2107
2206
  *
2108
- * データ検証の規則語彙と純関数の判定エンジン (v0.8 — getCellValidation 能力、ADR-13)。
2109
- * consumer が任意能力 getCellValidation(row, col) で規則を宣言し、エディタが確定時に
2110
- * validateCellText (custom 規則にはアダプタの数式評価器を渡す)、グリッドが描画時に
2111
- * isVisiblyInvalid (数式は決して評価しない) を呼んで不正インジケータを描く。React 非依存・全域関数。
2112
- * エンジン契約 (全て変異検証で封印 — spec 01 §8.3): 空文字は常に有効 (Excel の「空白を無視」—
2113
- * 検証セルは必ず消去できる、custom も評価しない)、number は cellFormat.ts と同じ厳密 10 進文法で
2114
- * 符号 / 有効数字 / 小数点位置の正規形として正確比較 (double 非経由)、date は Date 非依存の純暦文法を
2115
- * タプル比較 (between は両端含み)、不完全な規則 (解釈不能な境界・between の b 欠落・needle 欠落) は
2116
- * 不活性 = 全受理 (書きかけの規則でセルを閉じ込めない、境界の入替もしない)、語彙外の type / op は
2117
- * consumer バグとして text に依らず RangeError、list の Set は規則 object 毎に WeakMap intern、
2118
- * メッセージは errorMessage (空文字も尊重) が無ければ組込みの英語要約、custom は evaluate 無しなら
2119
- * 未評価 (ok)・真 = true か有限非 0 数、照合は完全一致 (大文字小文字区別・trim 無し)、textLength は
2120
- * コードポイント数、isEmail は WHATWG 文法 + ドット付きドメイン必須、isUrl は WHATWG 絶対 http(s) URL。
2121
- */
2207
+ * @param rule - The cell's data-validation rule / セルのデータ検証規則
2208
+ * @param text - The committed text / 確定テキスト
2209
+ * @param locale - The UI chrome locale of the built-in message ("en" | "ja"; required) / 組込みメッセージの UI クロームロケール ("en" | "ja"、必須)
2210
+ * @param evaluate - The consumer's formula evaluator for `custom` rules (omit to leave them unevaluated) / custom 規則用の consumer の数式評価器 (省略で未評価)
2211
+ * @returns The frozen shared ok verdict, or a rejection carrying the resolved message / 共有の凍結 ok 判定、または解決済みメッセージ付きの拒否
2212
+ * @throws {RangeError} When `locale` is not a supported SpreadsheetLocale (`undefined`, `null`,
2213
+ * `"EN"`, `"ja-JP"`, ...), or the rule's `type` / `op` is outside the vocabulary / `locale` が
2214
+ * 対応 SpreadsheetLocale でない場合 (`undefined`、`null`、`"EN"`、`"ja-JP"` など)、または規則の
2215
+ * type / op が語彙外の場合
2216
+ */
2217
+ export declare const validateCellText: (rule: DataValidationRule, text: string, locale: SpreadsheetLocale, evaluate?: ValidationEvaluate) => ValidationVerdict;
2218
+
2122
2219
  /** Ordered comparison vocabulary shared by number / textLength / date rules; between / notBetween include both bounds. / number / textLength / date 規則が共有する比較語彙。between / notBetween は両端含み。 */
2123
2220
  export declare type ValidationCompareOp = "gt" | "gte" | "lt" | "lte" | "eq" | "neq" | "between" | "notBetween";
2124
2221