@aiquants/virtualscroll 3.10.0 → 3.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/logger.d.cts CHANGED
@@ -44,7 +44,7 @@ export interface ILogger {
44
44
  */
45
45
  export declare class Logger implements ILogger {
46
46
  private level;
47
- private prefix;
47
+ private readonly prefix;
48
48
  private impl;
49
49
  /**
50
50
  * @constructor
@@ -82,20 +82,6 @@ export declare class Logger implements ILogger {
82
82
  * @param {ILogger} impl - The new logger implementation.
83
83
  */
84
84
  setImplementation(impl: ILogger): void;
85
- /**
86
- * @method setPrefix
87
- * @description Updates the log prefix for the static instance.
88
- * @description 静的インスタンスのログのプレフィックスを更新します。
89
- * @param {string} prefix - The new prefix.
90
- */
91
- static setPrefix(prefix: string): void;
92
- /**
93
- * @method setPrefix
94
- * @description Updates the log prefix.
95
- * @description ログのプレフィックスを更新します。
96
- * @param {string} prefix - The new prefix.
97
- */
98
- setPrefix(prefix: string): void;
99
85
  /**
100
86
  * @method isEnabled
101
87
  * @description Returns whether the given level would be emitted at the current level (static instance).
@@ -136,7 +122,6 @@ export declare class Logger implements ILogger {
136
122
  private formatMessage;
137
123
  static debug(message?: unknown, ...optionalParams: unknown[]): void;
138
124
  debug(message?: unknown, ...optionalParams: unknown[]): void;
139
- static info(message?: unknown, ...optionalParams: unknown[]): void;
140
125
  info(message?: unknown, ...optionalParams: unknown[]): void;
141
126
  static warn(message?: unknown, ...optionalParams: unknown[]): void;
142
127
  warn(message?: unknown, ...optionalParams: unknown[]): void;
package/dist/logger.d.ts CHANGED
@@ -44,7 +44,7 @@ export interface ILogger {
44
44
  */
45
45
  export declare class Logger implements ILogger {
46
46
  private level;
47
- private prefix;
47
+ private readonly prefix;
48
48
  private impl;
49
49
  /**
50
50
  * @constructor
@@ -82,20 +82,6 @@ export declare class Logger implements ILogger {
82
82
  * @param {ILogger} impl - The new logger implementation.
83
83
  */
84
84
  setImplementation(impl: ILogger): void;
85
- /**
86
- * @method setPrefix
87
- * @description Updates the log prefix for the static instance.
88
- * @description 静的インスタンスのログのプレフィックスを更新します。
89
- * @param {string} prefix - The new prefix.
90
- */
91
- static setPrefix(prefix: string): void;
92
- /**
93
- * @method setPrefix
94
- * @description Updates the log prefix.
95
- * @description ログのプレフィックスを更新します。
96
- * @param {string} prefix - The new prefix.
97
- */
98
- setPrefix(prefix: string): void;
99
85
  /**
100
86
  * @method isEnabled
101
87
  * @description Returns whether the given level would be emitted at the current level (static instance).
@@ -136,7 +122,6 @@ export declare class Logger implements ILogger {
136
122
  private formatMessage;
137
123
  static debug(message?: unknown, ...optionalParams: unknown[]): void;
138
124
  debug(message?: unknown, ...optionalParams: unknown[]): void;
139
- static info(message?: unknown, ...optionalParams: unknown[]): void;
140
125
  info(message?: unknown, ...optionalParams: unknown[]): void;
141
126
  static warn(message?: unknown, ...optionalParams: unknown[]): void;
142
127
  warn(message?: unknown, ...optionalParams: unknown[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,oBAAY,QAAQ;IAChB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;CACX;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACpB,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC3D,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC3D,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;CAC/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,MAAO,YAAW,OAAO;IAClC,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,IAAI,CAAS;IAErB;;;;;OAKG;gBACS,KAAK,GAAE,QAAwB,EAAE,MAAM,GAAE,MAA0B,EAAE,IAAI,GAAE,OAAiB;IAMxG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuD;IAE9E;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAItC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;;;;OAKG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI7C;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAItC;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAItC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAI1C;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAInC;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAc1B,OAAO,CAAC,aAAa;IAOrB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAInE,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM5D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAIlE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM3D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAIlE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM3D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAInE,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;CAK/D"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,oBAAY,QAAQ;IAChB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;CACX;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACpB,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC3D,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC3D,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;CAC/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,MAAO,YAAW,OAAO;IAClC,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,IAAI,CAAS;IAErB;;;;;OAKG;gBACS,KAAK,GAAE,QAAwB,EAAE,MAAM,GAAE,MAA0B,EAAE,IAAI,GAAE,OAAiB;IAMxG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuD;IAE9E;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAItC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;;;;OAKG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI7C;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAItC;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAI1C;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAInC;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAc1B,OAAO,CAAC,aAAa;IAOrB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAInE,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM5D,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM3D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAIlE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAM3D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;IAInE,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI;CAK/D"}
@@ -73,6 +73,12 @@ export declare class FenwickMapTree {
73
73
  */
74
74
  private valueFn?;
75
75
  private total?;
76
+ /**
77
+ * @private
78
+ * @property {number} revisionCount - The counter behind `revision`: raised by every change of a stored value or of the size.
79
+ * @property {number} revisionCount - `revision` の元の数。保持する値か要素数が変わるたびに上がる。
80
+ */
81
+ private revisionCount;
76
82
  /**
77
83
  * @constructor
78
84
  * @description Initializes the Fenwick Tree.
@@ -291,7 +297,7 @@ export declare class FenwickMapTree {
291
297
  * @description Rebuilds the Fenwick Tree from the existing `baseValue` and `deltas`. This corrects any discrepancies in the tree's internal state, such as those caused by floating-point errors, by recalculating the tree structure and the total sum from the source `deltas`. This method does not re-materialize values from `valueFn`.
292
298
  * @description 既存の `baseValue` と `deltas` から Fenwick Tree を再構築します。これにより、`deltas` からツリー構造と合計値を再計算することで、浮動小数点誤差などによって生じた内部状態の不一致を修正します。このメソッドは `valueFn` から値を再具現化しません。
293
299
  * @param {object} [options] - Optional settings for rebuilding.
294
- * @param {boolean} [options.materialize=false] - If true and `valueFn` is provided, re-materializes all values, recalculating `deltas` and `baseValue`.
300
+ * @param {boolean} [options.materialize=false] - If true and `valueFn` is set, rebuilds from `valueFn` instead: a reset with materialization (`reset(size, valueFn, { materialize: true })`) that re-samples `baseValue`, materializes the initial window (rows 0 to `SAMPLE_COUNT - 1`) and discards every other measured delta. A tree with a uniform value (no `valueFn`) rebuilds from its deltas either way. / true かつ `valueFn` があれば、代わりに `valueFn` から作り直す。具現化付きのリセット (`reset(size, valueFn, { materialize: true })`) で、`baseValue` を標本で決め直し、初期の窓 (行 0〜`SAMPLE_COUNT - 1`) を具現化し、ほかの測った差分はすべて捨てる。一様な値の木 (`valueFn` 無し) はどちらでも差分から作り直す。
295
301
  */
296
302
  rebuildTree(options?: {
297
303
  materialize?: boolean;
@@ -408,6 +414,20 @@ export declare class FenwickMapTree {
408
414
  * @returns {number} The base value. 基準値。
409
415
  */
410
416
  get base(): number;
417
+ /**
418
+ * @description Gets the tree's revision: a counter that rises whenever a value the tree stores or its size changes — an
419
+ * update, a materialization that changes a row, a reset, a resize, a new uniform value or a rebuild — and stays the same
420
+ * otherwise (reads, a materialization that finds the stored value, an update to the same value, a resize to the same size).
421
+ * The tree keeps its identity while its contents change, so a caller that derives anything from the prefix sums (row tops,
422
+ * a rendering range) compares two reads: equal reads mean nothing it derived became stale in between. The counter only
423
+ * rises; how far it rises per change is unspecified.
424
+ * @description 木の版を取得。木が保持する値か要素数が変わるたび (更新・行を変える具現化・リセット・要素数の変更・一様な値の
425
+ * 差し替え・再構築) に上がり、それ以外 (読み取り・保持する値と同じ値を見つけた具現化・同じ値への更新・同じ要素数への変更) では
426
+ * 変わらない数。木は中身が変わっても同一性を保つため、接頭辞和から何か (行の上端・描画範囲) を導く呼び出し側は 2 回の読み取りを
427
+ * 比べ、等しければその間に導いたものは古くなっていない。数は上がるだけで、1 回の変化でいくつ上がるかは決めない。
428
+ * @returns {number} The revision. 版。
429
+ */
430
+ get revision(): number;
411
431
  /**
412
432
  * @method findIndexAtOrAfter
413
433
  * @description Finds the first index where the cumulative sum is greater than or equal to a target value.
@@ -73,6 +73,12 @@ export declare class FenwickMapTree {
73
73
  */
74
74
  private valueFn?;
75
75
  private total?;
76
+ /**
77
+ * @private
78
+ * @property {number} revisionCount - The counter behind `revision`: raised by every change of a stored value or of the size.
79
+ * @property {number} revisionCount - `revision` の元の数。保持する値か要素数が変わるたびに上がる。
80
+ */
81
+ private revisionCount;
76
82
  /**
77
83
  * @constructor
78
84
  * @description Initializes the Fenwick Tree.
@@ -291,7 +297,7 @@ export declare class FenwickMapTree {
291
297
  * @description Rebuilds the Fenwick Tree from the existing `baseValue` and `deltas`. This corrects any discrepancies in the tree's internal state, such as those caused by floating-point errors, by recalculating the tree structure and the total sum from the source `deltas`. This method does not re-materialize values from `valueFn`.
292
298
  * @description 既存の `baseValue` と `deltas` から Fenwick Tree を再構築します。これにより、`deltas` からツリー構造と合計値を再計算することで、浮動小数点誤差などによって生じた内部状態の不一致を修正します。このメソッドは `valueFn` から値を再具現化しません。
293
299
  * @param {object} [options] - Optional settings for rebuilding.
294
- * @param {boolean} [options.materialize=false] - If true and `valueFn` is provided, re-materializes all values, recalculating `deltas` and `baseValue`.
300
+ * @param {boolean} [options.materialize=false] - If true and `valueFn` is set, rebuilds from `valueFn` instead: a reset with materialization (`reset(size, valueFn, { materialize: true })`) that re-samples `baseValue`, materializes the initial window (rows 0 to `SAMPLE_COUNT - 1`) and discards every other measured delta. A tree with a uniform value (no `valueFn`) rebuilds from its deltas either way. / true かつ `valueFn` があれば、代わりに `valueFn` から作り直す。具現化付きのリセット (`reset(size, valueFn, { materialize: true })`) で、`baseValue` を標本で決め直し、初期の窓 (行 0〜`SAMPLE_COUNT - 1`) を具現化し、ほかの測った差分はすべて捨てる。一様な値の木 (`valueFn` 無し) はどちらでも差分から作り直す。
295
301
  */
296
302
  rebuildTree(options?: {
297
303
  materialize?: boolean;
@@ -408,6 +414,20 @@ export declare class FenwickMapTree {
408
414
  * @returns {number} The base value. 基準値。
409
415
  */
410
416
  get base(): number;
417
+ /**
418
+ * @description Gets the tree's revision: a counter that rises whenever a value the tree stores or its size changes — an
419
+ * update, a materialization that changes a row, a reset, a resize, a new uniform value or a rebuild — and stays the same
420
+ * otherwise (reads, a materialization that finds the stored value, an update to the same value, a resize to the same size).
421
+ * The tree keeps its identity while its contents change, so a caller that derives anything from the prefix sums (row tops,
422
+ * a rendering range) compares two reads: equal reads mean nothing it derived became stale in between. The counter only
423
+ * rises; how far it rises per change is unspecified.
424
+ * @description 木の版を取得。木が保持する値か要素数が変わるたび (更新・行を変える具現化・リセット・要素数の変更・一様な値の
425
+ * 差し替え・再構築) に上がり、それ以外 (読み取り・保持する値と同じ値を見つけた具現化・同じ値への更新・同じ要素数への変更) では
426
+ * 変わらない数。木は中身が変わっても同一性を保つため、接頭辞和から何か (行の上端・描画範囲) を導く呼び出し側は 2 回の読み取りを
427
+ * 比べ、等しければその間に導いたものは古くなっていない。数は上がるだけで、1 回の変化でいくつ上がるかは決めない。
428
+ * @returns {number} The revision. 版。
429
+ */
430
+ get revision(): number;
411
431
  /**
412
432
  * @method findIndexAtOrAfter
413
433
  * @description Finds the first index where the cumulative sum is greater than or equal to a target value.
@@ -1 +1 @@
1
- {"version":3,"file":"useFenwickMapTree.d.ts","sourceRoot":"","sources":["../src/useFenwickMapTree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFenwickMapTree.d.ts","sourceRoot":"","sources":["../src/useFenwickMapTree.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useLruCache.d.ts","sourceRoot":"","sources":["../src/useLruCache.ts"],"names":[],"mappings":"AA4HA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM;eAwDhB,CAAC,KAAG,CAAC,GAAG,SAAS;eAqBjB,CAAC,SAAS,CAAC;eA6CX,CAAC,KAAG,OAAO;kBAWR,CAAC;;EA2BrC"}
1
+ {"version":3,"file":"useLruCache.d.ts","sourceRoot":"","sources":["../src/useLruCache.ts"],"names":[],"mappings":"AAsIA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM;eAoDhB,CAAC,KAAG,CAAC,GAAG,SAAS;eAqBjB,CAAC,SAAS,CAAC;eA6CX,CAAC,KAAG,OAAO;kBAWR,CAAC;;EA2BrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/virtualscroll",
3
- "version": "3.10.0",
3
+ "version": "3.11.0",
4
4
  "description": "High-performance virtual scrolling component for React with variable item heights",
5
5
  "sideEffects": [
6
6
  "**/*.css"
package/src/ScrollBar.tsx CHANGED
@@ -7,7 +7,7 @@ import type { CSSProperties, ReactNode } from "react"
7
7
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"
8
8
  import { twMerge } from "tailwind-merge"
9
9
  import { snapToDevicePixelGrid, usePaintingDevicePixelRatio } from "./devicePixelGrid.ts"
10
- import { resolveVirtualScrollLabels, type VirtualScrollLabelOverrides, type VirtualScrollLabels, type VirtualScrollLocale } from "./labels.ts"
10
+ import { resolveVirtualScrollLabels, resolveVirtualScrollLocale, type VirtualScrollLabelOverrides, type VirtualScrollLabels, type VirtualScrollLocale } from "./labels.ts"
11
11
  import { Logger } from "./logger.ts"
12
12
  import { capturePointer, releaseCapturedPointer } from "./pointerCapture.ts"
13
13
  import { TapScrollCircle, type TapScrollCircleDragState, type TapScrollCircleHandle, type TapScrollCircleRenderProps } from "./TapScrollCircle.tsx"
@@ -40,6 +40,13 @@ type ArrowAutoRepeatOptions = {
40
40
  canUseArrowButtons: boolean
41
41
  /** Whether arrow buttons are enabled in configuration / 設定で矢印ボタンが有効化されているか */
42
42
  enableArrowButtons: boolean
43
+ /**
44
+ * Whether a focused arrow takes Enter / Space: `false` under the pointer-only signal (`enableArrowButtonTabStops: false`),
45
+ * where the bar is hidden from assistive technology and its arrows answer the pointer only, even when a script focuses one.
46
+ * フォーカスした矢印が Enter / Space を受けるか。ポインタ専用の合図 (`enableArrowButtonTabStops: false`) の下では `false` で、
47
+ * バーは支援技術から隠れ、矢印はスクリプトがフォーカスしてもポインタにだけ応える。
48
+ */
49
+ keyboardOperable: boolean
43
50
  /** Function to reset tap scroll state / タップスクロール状態をリセットする関数 */
44
51
  resetTapScroll: () => void
45
52
  /** Function to scroll by a step / ステップ単位でスクロールする関数 */
@@ -154,8 +161,8 @@ export type ScrollBarProps = {
154
161
  viewportSize: number
155
162
  /** The current scroll position. / 現在のスクロール位置。 */
156
163
  scrollPosition: number
157
- /** A callback function invoked to adjust scroll position. Accepts next position or updater. / スクロール位置を調整するためのコールバック。次位置または更新関数を受け取る。 */
158
- onScroll?: (scrollPosition: number | ((prevPosition: number) => number), prevPosition?: number) => number | undefined
164
+ /** A callback function invoked to adjust scroll position. Accepts next position or updater, and always receives the position the bar resolved the request from. / スクロール位置を調整するためのコールバック。次位置または更新関数と、バーが要求を解いた元の位置 (必ず渡す) を受け取る。 */
165
+ onScroll?: (scrollPosition: number | ((prevPosition: number) => number), prevPosition: number) => number | undefined
159
166
  /** Whether grabbing the scrollbar thumb is allowed. / スクロールバーのつまみ操作を許可するかどうか。 */
160
167
  enableThumbDrag?: boolean
161
168
  /** Whether clicking on the track moves the scrollbar. / スクロールバーのトラッククリック操作を許可するかどうか。 */
@@ -235,10 +242,11 @@ export type ScrollBarProps = {
235
242
  /** The index of the last visible item. / 最後の可視アイテムのインデックス。 */
236
243
  visibleEndIndex?: number
237
244
  /**
238
- * UI chrome locale of the built-in accessible names of the bar, its thumb and its arrows (default `"en"`). An
239
- * unsupported value throws a RangeError at render; no language negotiation happens.
240
- * バー・つまみ・矢印の内蔵アクセシブルネームの UI クロームロケール (既定 `"en"`)。非対応値は描画時に RangeError、
241
- * 言語ネゴシエーションなし。
245
+ * UI chrome locale of the built-in accessible names of the bar, its thumb and its arrows, and of the percentage the bar
246
+ * and the thumb announce as their value text (default `"en"`). An unsupported value throws a RangeError at render; no
247
+ * language negotiation happens.
248
+ * バー・つまみ・矢印の内蔵アクセシブルネームと、バーとつまみが値の文字として知らせる百分率の UI クロームロケール (既定
249
+ * `"en"`)。非対応値は描画時に RangeError、言語ネゴシエーションなし。
242
250
  */
243
251
  locale?: VirtualScrollLocale
244
252
  /**
@@ -407,7 +415,7 @@ const useThumbVisualFeedback = ({ isDragging, isThumbHovered, enableThumbDrag }:
407
415
  *
408
416
  * スクロールバー矢印の自動リピート操作向けハンドラーを提供。
409
417
  */
410
- const useArrowAutoRepeat = ({ canUseArrowButtons, enableArrowButtons, resetTapScroll, scrollByStep }: ArrowAutoRepeatOptions): ArrowAutoRepeatHandlers => {
418
+ const useArrowAutoRepeat = ({ canUseArrowButtons, enableArrowButtons, keyboardOperable, resetTapScroll, scrollByStep }: ArrowAutoRepeatOptions): ArrowAutoRepeatHandlers => {
411
419
  const arrowHoldIntervalRef = useRef<number | null>(null)
412
420
  const arrowHoldTimeoutRef = useRef<number | null>(null)
413
421
  // 長押し中に張るグローバル解除リスナ (disabled 化やウィンドウ blur でボタンに pointerup が届かない保険)。
@@ -463,7 +471,9 @@ const useArrowAutoRepeat = ({ canUseArrowButtons, enableArrowButtons, resetTapSc
463
471
 
464
472
  const handleArrowKeyDown = useCallback(
465
473
  (direction: 1 | -1) => (event: React.KeyboardEvent<HTMLButtonElement>) => {
466
- if (!enableArrowButtons) {
474
+ // ポインタ専用のバーは支援技術から隠れていて、キーボードのスクロールはホストが持つ。スクリプトがフォーカスした矢印でも
475
+ // キーを受けると、隠れた部品がホストのキー操作と重なって一覧を動かす
476
+ if (!(enableArrowButtons && keyboardOperable)) {
467
477
  return
468
478
  }
469
479
  if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
@@ -471,7 +481,7 @@ const useArrowAutoRepeat = ({ canUseArrowButtons, enableArrowButtons, resetTapSc
471
481
  scrollByStep(direction)
472
482
  }
473
483
  },
474
- [enableArrowButtons, scrollByStep],
484
+ [enableArrowButtons, keyboardOperable, scrollByStep],
475
485
  )
476
486
 
477
487
  // 矢印ボタンが操作不能 (canUseArrowButtons=false) になったら進行中のリピートを即停止する。
@@ -729,6 +739,8 @@ export const ScrollBar = ({
729
739
  const orientationConfig = useMemo(() => createOrientationConfig(horizontal), [horizontal])
730
740
  const resolvedLabels = useMemo(() => resolveVirtualScrollLabels(locale, labels), [locale, labels])
731
741
  const names = pickScrollBarNames(resolvedLabels, horizontal)
742
+ // 値の文字はスクロールの割合。px の値 (aria-valuenow) は長い一覧で数千万になり、読み上げても位置が分からない
743
+ const valueTextFormat = useMemo(() => new Intl.NumberFormat(resolveVirtualScrollLocale(locale), { style: "percent", maximumFractionDigits: 0 }), [locale])
732
744
  // ホストがキーボードのスクロールを持つと、バーはその経路の重複になる。支援技術にもキーボードにも同じ操作を 2 度見せない
733
745
  const pointerOnly = !enableArrowButtonTabStops
734
746
  const {
@@ -768,6 +780,9 @@ export const ScrollBar = ({
768
780
  // 負値が aria-valuemax へ露出して ARIA 違反 (valuemax < valuemin) になる。644 行の
769
781
  // getScrollBarMetrics と同一のクランプ規約)
770
782
  const maxScrollPosition = Math.max(contentSize - viewportSize, 0)
783
+ // ポインタ専用のバーは支援技術から隠れるので値の文字を持たない。スクロールできないバーは 0 %、中身が縮んで一時的に最大位置を
784
+ // 越えた位置は 100 %
785
+ const valueText = pointerOnly ? undefined : valueTextFormat.format(maxScrollPosition > 0 ? minmax(scrollPosition / maxScrollPosition, 0, 1) : 0)
771
786
  const effectiveTrackLength = Math.max(trackLength - thumbSize, 0)
772
787
  // scrollPosition が範囲外 (コンテンツ縮小直後の未クランプ 1 フレームや iOS バウンス値) でも
773
788
  // サムがトラック外へはみ出さないよう、レンダー時に [0, effectiveTrackLength] へクランプする。
@@ -1303,6 +1318,7 @@ export const ScrollBar = ({
1303
1318
  const { handleArrowPointerDown, handleArrowPointerUp, handleArrowKeyDown } = useArrowAutoRepeat({
1304
1319
  canUseArrowButtons,
1305
1320
  enableArrowButtons,
1321
+ keyboardOperable: !pointerOnly,
1306
1322
  resetTapScroll,
1307
1323
  scrollByStep,
1308
1324
  })
@@ -1598,6 +1614,7 @@ export const ScrollBar = ({
1598
1614
  aria-valuenow={scrollPosition}
1599
1615
  aria-valuemin={0}
1600
1616
  aria-valuemax={maxScrollPosition}
1617
+ aria-valuetext={valueText}
1601
1618
  aria-orientation={horizontal ? "horizontal" : "vertical"}>
1602
1619
  {(!horizontal || enableHorizontalTapCircle) && scrollBarVisible && tapCircleEnabled && (
1603
1620
  <TapScrollCircle
@@ -1653,6 +1670,7 @@ export const ScrollBar = ({
1653
1670
  aria-valuenow={scrollPosition}
1654
1671
  aria-valuemin={0}
1655
1672
  aria-valuemax={maxScrollPosition}
1673
+ aria-valuetext={valueText}
1656
1674
  aria-disabled={!enableThumbDrag}
1657
1675
  tabIndex={pointerOnly ? undefined : -1}>
1658
1676
  {/* スクロールバーのつまみ(可視部分) */}
@@ -605,9 +605,7 @@ const EMPTY_PLACED_COLUMNS: PlacedColumn[] = []
605
605
  const collectVisibleColumns = (startCol: number, endCol: number, getColWidth: (col: number) => number, colTree: ReturnType<typeof useFenwickMapTree>, maxColumns: number): { columns: PlacedColumn[]; widthUpdates: Array<{ index: number; value: number }>; truncated: number } => {
606
606
  const columns: PlacedColumn[] = []
607
607
  const widthUpdates: Array<{ index: number; value: number }> = []
608
- if (endCol < startCol) {
609
- return { columns, widthUpdates, truncated: 0 }
610
- }
608
+ // 呼び出し元は空窓 (start > end) を先に除くので、ここへ来る窓は 1 列以上
611
609
  const startPrefix = colTree.prefixSum(startCol, { materializeOption: { materialize: false } })
612
610
  // 窓先頭の絶対 left から幅を積む O(k) 走査 (列ごとの prefixSum O(k·log n) を回避 — 行 memo と同型)
613
611
  let runningLeft = startPrefix.cumulative - startPrefix.currentValue
@@ -850,8 +848,8 @@ const VirtualGridInner = <T,>(
850
848
  const colTree = useFenwickMapTree(colCount, validatedGetColWidth, colTreeOptions)
851
849
 
852
850
  // ---- 幅エポック (木の内容バージョン): updateColSize / self-heal 適用で繰上げ、窓キー不変でも
853
- // 配置 memo と列窓再計算を失効させる。行側は総高 (contentSize) を反応辺にするが、相殺
854
- // バッチリサイズ (総和不変) も拾えるようエポックはその厳密上位互換 ----
851
+ // 配置 memo と列窓再計算を失効させる。総幅は相殺バッチリサイズ (総和不変) で変わらないため
852
+ // 合図にならない (行側は VirtualScroll の木の版数が同じ役目を持つ) ----
855
853
  const [widthEpoch, setWidthEpoch] = useState(0)
856
854
 
857
855
  // ---- 凍結帯 (設計 §8) — 形状検証は fail-fast、colCount 超過だけは動的クランプ (シート
@@ -982,7 +980,7 @@ const VirtualGridInner = <T,>(
982
980
  /** Anchor the DOM currently shows (updated post-commit in the layout effect). / DOM が現在表示中のアンカー (commit 後の layout effect で更新)。 */
983
981
  const committedAnchorRef = useRef(0)
984
982
 
985
- const [totalWidth, setTotalWidth] = useState(() => colTree.getTotal() ?? 0)
983
+ const [totalWidth, setTotalWidth] = useState(() => colTree.getTotal())
986
984
  const totalWidthRef = useRef(totalWidth)
987
985
  totalWidthRef.current = totalWidth
988
986
  /** Mirrors the tree total into state+ref immediately (same tick — drag loops clamp fresh). / 木総幅を state + ref へ即時反映 (同 tick — ドラッグループが新鮮にクランプ)。 */
@@ -1715,11 +1713,14 @@ const VirtualGridInner = <T,>(
1715
1713
  // ---- liveRegion (2D — 文言は消費側所有、静定デバウンス) ----
1716
1714
  const [liveMessage, setLiveMessage] = useState("")
1717
1715
  const liveTimerRef = useRef<number | null>(null)
1716
+ // 埋め込みの一覧はアンマウントで待っていた範囲の通知を同期で配る (取りこぼさないため)。それはグリッド自身の後始末の後に
1717
+ // 届くので、アンマウントの後は読み上げを予約しない (予約すると消費側の buildMessage がアンマウントの後に走る)
1718
+ const isLiveRegionClosedRef = useRef(false)
1718
1719
  const liveRegionRef = useRef(liveRegion)
1719
1720
  liveRegionRef.current = liveRegion
1720
1721
  const scheduleLiveMessage = useCallback(() => {
1721
1722
  const options = liveRegionRef.current
1722
- if (options === undefined) {
1723
+ if (options === undefined || isLiveRegionClosedRef.current) {
1723
1724
  return
1724
1725
  }
1725
1726
  // 不正な debounceMs は黙って既定へ読み替えず読み上げを無効化する (警告は下の effect が 1 回だけ出す)
@@ -1734,10 +1735,8 @@ const VirtualGridInner = <T,>(
1734
1735
  liveTimerRef.current = null
1735
1736
  const range = buildRange()
1736
1737
  if (range !== null) {
1737
- setLiveMessage((prev) => {
1738
- const next = options.buildMessage(range)
1739
- return next === prev ? prev : next
1740
- })
1738
+ // 同じ文言の再設定は React が Object.is で捨てる (再描画しない) ので、比べずに書く (行側のライブリージョンと同じ)
1739
+ setLiveMessage(options.buildMessage(range))
1741
1740
  }
1742
1741
  }, debounce)
1743
1742
  }, [buildRange])
@@ -1750,14 +1749,16 @@ const VirtualGridInner = <T,>(
1750
1749
  Logger.warn(`[VirtualGrid] liveRegion.debounceMs must be a finite number >= 0, received ${liveDebounceMs}. Announcements are disabled.`)
1751
1750
  }
1752
1751
  }, [hasLiveRegion, liveDebounceValid, liveDebounceMs])
1753
- useEffect(
1754
- () => () => {
1752
+ useEffect(() => {
1753
+ // StrictMode の二重マウント (後始末の後に再び effect) でも読み上げを再開できるよう、本体で開き直す
1754
+ isLiveRegionClosedRef.current = false
1755
+ return () => {
1756
+ isLiveRegionClosedRef.current = true
1755
1757
  if (liveTimerRef.current !== null) {
1756
1758
  window.clearTimeout(liveTimerRef.current)
1757
1759
  }
1758
- },
1759
- [],
1760
- )
1760
+ }
1761
+ }, [])
1761
1762
  useEffect(() => {
1762
1763
  scheduleLiveMessage()
1763
1764
  }, [columnWindow, scheduleLiveMessage])
@@ -1849,9 +1850,10 @@ const VirtualGridInner = <T,>(
1849
1850
  if (found.cumulative === bandStart) {
1850
1851
  return { row: rowAnchor.index + effectiveFrozenRows, col: minmax(found.index + 1, 0, colCount - 1), offsetX: 0, offsetY: rowAnchor.offsetPx }
1851
1852
  }
1853
+ // 見つけた列の左端は木から読み直す (探索の結果の型は列が無い場合の undefined を含むため)
1854
+ const column = colTree.prefixSum(found.index, { materializeOption: { materialize: false } })
1852
1855
  // 行はシフト空間 → フル行空間へ +R 翻訳 (行凍結設計 §3 — 復元側は −R で往復恒等)
1853
- const colLeft = (found.cumulative ?? 0) - (found.currentValue ?? 0)
1854
- return { row: rowAnchor.index + effectiveFrozenRows, col: found.index, offsetX: Math.max(0, bandStart - colLeft), offsetY: rowAnchor.offsetPx }
1856
+ return { row: rowAnchor.index + effectiveFrozenRows, col: found.index, offsetX: Math.max(0, bandStart - (column.cumulative - column.currentValue)), offsetY: rowAnchor.offsetPx }
1855
1857
  },
1856
1858
  getViewportSize: () => ({ width: viewportRef.current.width, height: viewportRef.current.height }),
1857
1859
  // 縦はインセット込みの行側 getContentSize を単一情報源にする (range.totalHeight は木総高のみ)。
@@ -2003,7 +2005,7 @@ const VirtualGridInner = <T,>(
2003
2005
  onScroll={(request, previous) => {
2004
2006
  // バー操作は手動横入力 — 列アンカーの張りを解除する
2005
2007
  pendingColAnchorRef.current = null
2006
- return applyHxRef.current(typeof request === "function" ? request(previous ?? hxRef.current) : request)
2008
+ return applyHxRef.current(typeof request === "function" ? request(previous) : request)
2007
2009
  }}
2008
2010
  // バー固有の設定は縦バー (内包 VirtualScroll へ scrollBarOptions を全量透過) と同じ値を
2009
2011
  // 横バーへも渡す — 片方のバーにだけ効く設定面を作らない